OSStatus SecDHCreate(uint32_t g, const uint8_t *p, size_t p_len, uint32_t l, const uint8_t *recip, size_t recip_len, SecDHContext *pdh) { cc_size n = ccn_nof_size(p_len); size_t context_size = SecDH_context_size(p_len); void *context = malloc(context_size); bzero(context, context_size); ccdh_gp_t gp; gp.gp = context; CCDH_GP_N(gp) = n; CCDH_GP_L(gp) = l; if(ccn_read_uint(n, CCDH_GP_PRIME(gp), p_len, p)) goto errOut; if(recip) { if(ccn_read_uint(n+1, CCDH_GP_RECIP(gp), recip_len, recip)) goto errOut; CCZP_MOD_PRIME(gp.zp) = cczp_mod; } else { cczp_init(gp.zp); }; ccn_seti(n, CCDH_GP_G(gp), g); *pdh = (SecDHContext) context; return errSecSuccess; errOut: SecDHDestroy(context); *pdh = NULL; return errSecInternal; }
int ccec_make_priv(size_t nbits, size_t xlength, uint8_t *x, size_t ylength, uint8_t *y, size_t klength, uint8_t *k, ccec_full_ctx_t key) { int result; ccec_const_cp_t cp = ccec_get_cp(nbits); ccec_ctx_init(cp, key); if ((result = ccn_read_uint(ccec_cp_n(cp), ccec_ctx_x(key), xlength, x))) goto errOut; if ((result = ccn_read_uint(ccec_cp_n(cp), ccec_ctx_y(key), ylength, y))) goto errOut; if ((result = ccn_read_uint(ccec_cp_n(cp), ccec_ctx_k(key), klength, k))) goto errOut; ccn_seti(ccec_cp_n(cp), ccec_ctx_z(key), 1); errOut: return result; }
int ccec_generate_key_internal_fips(ccec_const_cp_t cp, struct ccrng_state *rng, ccec_full_ctx_t key) { int result=CCEC_GENERATE_KEY_DEFAULT_ERR; /* Get base point G in projected form. */ ccec_point_decl_cp(cp, base); cczp_const_t zq = ccec_cp_zq(cp); cc_require((result=ccec_projectify(cp, base, ccec_cp_g(cp),rng))==0,errOut); /* Generate a random private key k. */ ccec_ctx_init(cp, key); cc_unit *k = ccec_ctx_k(key); cc_unit *q_minus_2 = ccec_ctx_x(key); // used as temp buffer int cmp_result=1; /* Need to test candidate against q-2 */ ccn_sub1(ccec_cp_n(cp), q_minus_2, cczp_prime(zq), 2); size_t i; /* Generate adequate random for private key */ for (i = 0; i < MAX_RETRY && cmp_result>0; i++) { /* Random bits */ cc_require(((result = ccn_random_bits(ccec_cp_order_bitlen(cp), k, rng)) == 0),errOut); /* If k <= q-2, the number is valid */ cmp_result=ccn_cmp(ccec_cp_n(cp), k, q_minus_2); } if (i >= MAX_RETRY) { result=CCEC_GENERATE_KEY_TOO_MANY_TRIES; } else { cc_assert(cmp_result<=0); /* k is now in range [ 0, q-2 ] ==> +1 for range [ 1, q-1 ] */ ccn_add1(ccec_cp_n(cp), k, k, 1); /* Calculate the public key for k. */ cc_require_action(ccec_mult(cp, ccec_ctx_point(key), k, base,rng) == 0 ,errOut, result=CCEC_GENERATE_KEY_MULT_FAIL); cc_require_action(ccec_is_point_projective(cp, ccec_ctx_point(key)),errOut, result=CCEC_GENERATE_NOT_ON_CURVE); cc_require_action(ccec_affinify(cp, ccec_ctx_point(key), ccec_ctx_point(key)) == 0,errOut, result=CCEC_GENERATE_KEY_AFF_FAIL); ccn_seti(ccec_cp_n(cp), ccec_ctx_z(key), 1); result=0; } errOut: return result; }
// 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; }
/* r = s^e (mod zp->prime). Caller provides recip of m as recip; s and r can have the same address. */ void cczp_powern(cczp_const_t zp, cc_unit *r, const cc_unit *s, size_t ebitlen, const cc_unit *e) { assert(r != s); assert(r != e); if (ebitlen == 0) { ccn_seti(cczp_n(zp), r, 1); return; } cczp_modn(zp, r, cczp_n(zp), s); if (ebitlen == 1) return; for (unsigned long bit = ebitlen - 2; bit < ebitlen; --bit) { cczp_mul(zp, r, r, r); // cczp_sqr if (ccn_bit(e, bit)) { cczp_mul(zp, r, r, s); } } }
/* r = s^e (mod zp->prime). Caller provides recip of m as recip; s and r can have the same address. */ void cczp_power(cczp_const_t zp, cc_unit *r, const cc_unit *s, const cc_unit *e) { cc_size n = cczp_n(zp); unsigned long ebitlen = ccn_bitlen(n, e); if (ebitlen == 0) { ccn_seti(n, r, 1); return; } CC_DECL_WORKSPACE(ws, CCZP_MUL_WORKSPACE_N(n)+n); cc_unit *r1=ws->start; ws->start+=n; /* do we actually need to handle this case where s>m */ if (ccn_cmp(cczp_n(zp), s, cczp_prime(zp)) >= 0) { cc_unit *tbig=ws->start; // 2*n buffer ws->start+=2*n; ccn_zero(n, tbig + n); ccn_set(n, tbig, s); cczp_mod(zp, r, tbig, ws); ws->start-=2*n; } else { ccn_set(n, r, s); } if (ebitlen != 1) { cc_unit *R[2] __attribute__((aligned(16)))={r,r1}; cczp_sqr_ws(zp, r1, r, ws); for (unsigned long bit = ebitlen - 2; bit < ebitlen; --bit) { cc_unit ki=ccn_bit(e, bit); cczp_mul_ws(zp, R[ki^1], R[ki], R[ki^1],ws); cczp_sqr_ws(zp, R[ki], R[ki], ws); } } ws->start-=n; // r CC_CLEAR_AND_FREE_WORKSPACE(ws); }
int ccrsa_test_verify_pkcs1v15_vector(const struct ccrsa_verify_vector *v) { bool ok; int rc; const struct ccdigest_info *di = v->di; const cc_size n = ccn_nof(v->modlen); const size_t s = ccn_sizeof(v->modlen); unsigned char H[di->output_size]; cc_unit exponent[n]; cc_unit modulus[n]; ccrsa_pub_ctx_decl(ccn_sizeof(v->modlen), key); ccrsa_ctx_n(key) = n; ccn_seti(n, exponent, v->exp); ccn_read_uint(n, modulus, s, v->mod); ccrsa_init_pub(key, modulus, exponent); ccdigest(di, v->msglen, v->msg, H); rc=ccrsa_verify_pkcs1v15(key, di->oid.oid, di->output_size, H, v->siglen, v->sig, &ok); return ((rc==0) && ((ok && v->valid) || (!ok && !v->valid)))?0:1; }