int cczp_random_prime(cc_size nbits, cczp_t zp, const cc_unit *e, struct ccrng_state *rng) { cc_size lbits = nbits & (CCN_UNIT_BITS - 1); lbits = lbits == 0 ? CCN_UNIT_BITS : lbits; cc_unit msuMask = (~CC_UNIT_C(0)) >> (CCN_UNIT_BITS - lbits); cc_unit msBit = CC_UNIT_C(1) << (lbits - 1); cc_size n = ccn_nof(nbits); CCZP_N(zp) = n; for (;;) { /* Generate nbit wide random ccn. */ if(ccn_random(n, CCZP_PRIME(zp), rng) != 0) return -1; /* Mask out unsued bit and set high bit. */ CCZP_PRIME(zp)[n - 1] = (cczp_prime(zp)[n - 1] & msuMask) | msBit; ccn_set_bit(CCZP_PRIME(zp), nbits - 2, 1); /* Set second highest bit per X9.31 */ ccn_set_bit(CCZP_PRIME(zp), 0U, 1); /* Make it odd: set bit 0 to 1 */ /* First ensure r - 1 and e are relatively prime */ cc_unit tmp[n]; ccn_sub1(n, tmp, cczp_prime(zp), 1); ccn_gcd(n, tmp, tmp, e); if (!ccn_is_one(n, tmp)) { //ccn_lprint(n, "gcd of r - 1 and e is ", tmp); continue; } if (cczp_rabin_miller(zp, CCRSA_PRIME_DEPTH)) break; } return 0; }
// Convert point from affine to jacobian projective coordinates int ccec_projectify(ccec_const_cp_t cp, ccec_projective_point_t r, ccec_const_affine_point_t s, struct ccrng_state *masking_rng) { int status; cc_assert(r.hdr!=s.hdr); // Points must differ #if CCEC_DEBUG ccec_alprint(cp, "ccec_projectify input", s); #endif // Initialize z #if CCEC_MASKING // Randomized z coordinate if (masking_rng) { cc_size bitlen=ccec_cp_prime_bitlen(cp); status=ccn_random_bits(bitlen-1, ccec_point_z(r, cp), masking_rng); ccn_set_bit(ccec_point_z(r, cp), bitlen-2, 1); cczp_sqr(cp.zp, ccec_point_x(r, cp), ccec_point_z(r, cp)); // Z^2 (mtgR^-1) cczp_mul(cp.zp, ccec_point_y(r, cp), ccec_point_x(r, cp), ccec_point_z(r, cp)); // Z^3 (mtgR^-2) // Set point coordinate from Z, Z^2, Z^3 cczp_mul(cp.zp, ccec_point_x(r, cp), ccec_point_x(r, cp), ccec_const_point_x(s, cp)); // x.Z^2.mtgR (mtgR^-3) cczp_mul(cp.zp, ccec_point_y(r, cp), ccec_point_y(r, cp), ccec_const_point_y(s, cp)); // y.Z^3.mtgR (mtgR^-4) // Z.mtgR (mtgR^-1) if (CCEC_ZP_IS_MONTGOMERY(cp)) { cczp_convert_to_montgomery(cp.zp, ccec_point_x(r, cp), ccec_point_x(r, cp)); // x.Z^2.mtgR (mtgR^-2) cczp_convert_to_montgomery(cp.zp, ccec_point_y(r, cp), ccec_point_y(r, cp)); // y.Z^3.mtgR (mtgR^-3) } // Z.mtgR (mtgR^-1) } else #endif // Fixed z coordinate { ccn_seti(ccec_cp_n(cp), ccec_point_z(r, cp),1); (void) masking_rng; // Set point in the arithmetic representation if (CCEC_ZP_IS_MONTGOMERY(cp)) { cczp_convert_to_montgomery(cp.zp, ccec_point_x(r, cp), ccec_const_point_x(s, cp)); cczp_convert_to_montgomery(cp.zp, ccec_point_y(r, cp), ccec_const_point_y(s, cp)); cczp_convert_to_montgomery(cp.zp, ccec_point_z(r, cp), ccec_point_z(r, cp)); } else { ccn_set(ccec_cp_n(cp), ccec_point_x(r, cp), ccec_const_point_x(s, cp)); ccn_set(ccec_cp_n(cp), ccec_point_y(r, cp), ccec_const_point_y(s, cp)); } status=0; } #if CCEC_DEBUG ccec_plprint(cp, "ccec_projectify output", r); #endif return status; }
/* q*t + r == s [e.g. s/t, q=quotient, r=remainder]. */ static void ccn_divn(cc_size nqs, cc_unit *q, cc_unit *r, const cc_unit *s, size_t nrt, cc_unit *t) { if (ccn_is_zero(nrt, t)) { /* Division by zero is illegal. */ return; } /* If s < t then q = 0, r = s */ if (ccn_cmpn(nqs, s, nrt, t) < 0) { if (r) ccn_setn(nrt, r, CC_MIN(nrt, nqs), s); if (q) ccn_zero(nqs, q); return; } /* s >= t => k >= 0 */ size_t k = ccn_bitlen(nqs, s); size_t l = ccn_bitlen(nrt, t); assert(k >= l); k -= l; cc_unit tr[nqs]; cc_unit tt[nqs]; cc_unit tq[nqs]; ccn_set(nqs, tr, s); ccn_setn(nqs, tt, nrt, t); ccn_shift_left_multi(nqs, tt, tt, k); ccn_zero(nqs, tq); for (;;) { if (ccn_cmp(nqs, tr, tt) >= 0) { ccn_sub(nqs, tr, tr, tt); ccn_set_bit(tq, k, 1); } if (!k) break; --k; ccn_shift_right(nqs, tt, tt, 1); } if (r) { ccn_setn(nrt, r, CC_MIN(nrt, nqs), tr); } if (q) { ccn_set(nqs, q, tq); } }
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; }
int ccdh_test_compute_vector(const struct ccdh_compute_vector *v) { int result,r1,r2; const cc_size n = ccn_nof(v->len); const size_t s = ccn_sizeof_n(n); unsigned char z[v->zLen]; size_t zLen; unsigned char tmp[v->zLen]; // for negative testing uint32_t status=0; uint32_t nb_test=0; ccdh_gp_decl(s, gp); ccdh_full_ctx_decl(s, a); ccdh_full_ctx_decl(s, b); cc_unit p[n]; cc_unit g[n]; cc_unit r[n]; cc_unit q[n]; // Bail to errOut when unexpected error happens. // Try all usecases otherwise if((result=ccn_read_uint(n, p, v->pLen, v->p))) goto errOut; if((result=ccn_read_uint(n, g, v->gLen, v->g))) goto errOut; if((result=ccn_read_uint(n, q, v->qLen, v->q))) goto errOut; ccdh_init_gp_with_order(gp, n, p, g, q); ccdh_ctx_init(gp, a); ccdh_ctx_init(gp, b); if((result=ccn_read_uint(n, ccdh_ctx_x(a), v->xaLen, v->xa))) // private key goto errOut; if((result=ccn_read_uint(n, ccdh_ctx_y(a), v->yaLen, v->ya))) // public key goto errOut; if((result=ccn_read_uint(n, ccdh_ctx_x(b), v->xbLen, v->xb))) // private key goto errOut; if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->ybLen, v->yb))) // public key goto errOut; /* * Main test */ /* try one side */ zLen = v->zLen; r1=ccdh_compute_key(a, b, r); ccn_write_uint_padded(n, r, zLen, z); r1|=memcmp(z, v->z, zLen); /* try the other side */ zLen = v->zLen; r2=ccdh_compute_key(b, a, r); ccn_write_uint_padded(n, r, zLen, z); r2|=memcmp(z, v->z, zLen); if ((!(r1||r2) && v->valid)||((r1||r2) && !v->valid)) { status|=1<<nb_test; } nb_test++; // We are done if the test is not valid if (!v->valid) goto doneOut; /* * Corner case / negative testing * Only applicable for valid tests */ /* Output is 1 (use private key is (p-1)/2)*/ if((result=ccn_read_uint(n, ccdh_ctx_x(a), v->pLen, v->p))) // private key goto errOut; ccn_sub1(n,ccdh_ctx_x(a),ccdh_ctx_x(a),1); ccn_shift_right(n,ccdh_ctx_x(a),ccdh_ctx_x(a),1); if ((result=ccdh_compute_key(a, b, r))!=0) { status|=1<<nb_test; } if((result=ccn_read_uint(n, ccdh_ctx_x(a), v->xaLen, v->xa))) // restore private key goto errOut; nb_test++; /* negative testing (1 < y < p-1)*/ /* public y = 0 */ zLen = v->zLen; cc_zero(sizeof(tmp),tmp); if((result=ccn_read_uint(n, ccdh_ctx_y(b), zLen, tmp))) { goto errOut; } if((result=ccdh_compute_key(a, b, r))!=0) { status|=1<<nb_test; } nb_test++; /* public y = 1 */ zLen = v->zLen; cc_zero(sizeof(tmp),tmp); tmp[zLen-1]=1; if((result=ccn_read_uint(n, ccdh_ctx_y(b), zLen, tmp))) { goto errOut; } if((result=ccdh_compute_key(a, b, r))!=0) { status|=1<<nb_test; } nb_test++; /* public y = p */ if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->pLen, v->p))) goto errOut; if((result=ccdh_compute_key(a, b, r))!=0) { status|=1<<nb_test; } nb_test++; /* public y = p-1 */ if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->pLen, v->p))) { goto errOut; } ccn_sub1(n,ccdh_ctx_y(b),ccdh_ctx_y(b),1); if((result=ccdh_compute_key(a, b, r))!=0) { status|=1<<nb_test; } nb_test++; /* * When the order is in defined in the group * check that the implementation check the order of the public value: * public y = g+1 (for rfc5114 groups, g+1 is not of order q) */ if (ccdh_gp_order_bitlen(gp)) { if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->gLen, v->g))) { goto errOut; } ccn_add1(n,ccdh_ctx_y(b),ccdh_ctx_y(b),1); if((result=ccdh_compute_key(a, b, r))!=0) { status|=1<<nb_test; } nb_test++; } /* positive testing at the boundaries of (1 < y < p-1)*/ // Don't set the order in gp because 2 and p-2 are not of order q ccdh_init_gp(gp, n, p, g, 0); /* public y = 2 */ zLen = v->zLen; cc_zero(sizeof(tmp),tmp); tmp[zLen-1]=2; if((result=ccn_read_uint(n, ccdh_ctx_y(b), zLen, tmp))) { goto errOut; } if((result=ccdh_compute_key(a, b, r))==0) { status|=1<<nb_test; } nb_test++; /* public y = p-2 */ if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->pLen, v->p))) { goto errOut; } ccn_sub1(n,ccdh_ctx_y(b),ccdh_ctx_y(b),2); if((result=ccdh_compute_key(a, b, r))==0) { status|=1<<nb_test; } nb_test++; /* Negative testing: p is even */ if((result=ccn_read_uint(n, p, v->pLen, v->p))) goto errOut; ccn_set_bit(p,0,0); // Set LS bit to 0 ccdh_init_gp(gp, n, p, g, 0); ccdh_ctx_init(gp, a); ccdh_ctx_init(gp, b); if((result=ccdh_compute_key(a, b, r))!=0) { status|=1<<nb_test; } nb_test++; /* Test aftermath */ doneOut: if ((nb_test==0) || (status!=((1<<nb_test)-1))) { result=1; } else { result=0; // Test is successful, Yeah! } errOut: return result; }