示例#1
0
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;
}
示例#2
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;
}
示例#3
0
/* 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);
    }
}
示例#4
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;
}
示例#5
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;
}