示例#1
0
int cczp_sqrt(cczp_const_t zp, cc_unit *r, const cc_unit *x) {
    cc_size n=cczp_n(zp);
    cc_unit t[n];
    ccn_set(n,t,cczp_prime(zp));
    int result = -1;
    
    // Square root can be computed as x^((p+1)/4) when p = 3 mod 4
    cc_require(((t[0]&3) == 3),errOut);
    
    // Compute ((p+1)/4)
    ccn_add1(n, t, t, 1);
    ccn_shift_right(n, t, t, 2);
    
    // Exponentiation
    cczp_power_fast(zp,r,x,t);
    
    // Confirm that the result is valid
    // => r is not the square root of x
    cczp_mul(zp,t,r,r);
    cc_require(ccn_cmp(n,t,x)==0,errOut); // r^2 == x ?
    
    result=0;
    
errOut:
    return result;
}
示例#2
0
static double perf_ccn_cmp(unsigned long loops, cc_size count)
{
    cc_unit s[count];
    cc_unit t[count];
    ccn_random(count, s, rng);
    ccn_set(count, t, s);
    perf_start();
    do {
        r_for_cmp=ccn_cmp(count, s, t);
    } while (--loops != 0);
    return perf_time();
}
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;
}
CC_INLINE bool
ccsrp_component_equal(char *label, ccsrp_ctx_t srp, cc_unit *a, cc_unit *b) {
    bool retval = ccn_cmp(ccsrp_ctx_n(srp), a, b) == 0;
    if(!retval) {
        size_t bytes_n = ccsrp_ctx_sizeof_n(srp);
        cc_printf("ccsrp_test_calculations: mismatch for %s:\n", label);
        cc_printf("\t");
        dump_hex((void *) a, bytes_n);
        cc_printf("\t");
        dump_hex((void *) b, bytes_n);
        cc_printf("\n");
    }
    return retval;
}
示例#5
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);
    }
}
示例#6
0
/* TODO: Potentially write and use ccn_lcm(n, r2n, s, t). */
void ccn_lcm(cc_size n, cc_unit *r2n, const cc_unit *s, const cc_unit *t) {
    cc_unit tmp[n*2];
    if (ccn_cmp(n, s, t) < 0)
        CC_SWAP(s,t);
    /* Now s >= t. */
    ccn_zero(n*2, r2n);

    ccn_gcd(n, r2n, s, t);
    
    cc_unit t2[n*2];
    ccn_setn(n*2, t2, n, t);
    
    ccn_divmod(n, tmp, NULL, t2, r2n);
    ccn_mul(n, r2n, s, tmp);
}
示例#7
0
int ccdh_import_priv(ccdh_const_gp_t gp, size_t in_len, const uint8_t *in,
                     ccdh_full_ctx_t key)
{
    const cc_unit *g = ccdh_gp_g(gp);
    ccdh_ctx_init(gp, key);
    cc_unit *x = ccdh_ctx_x(key);
    cc_unit *y = ccdh_ctx_y(key);

    if ((ccn_read_uint(ccdh_gp_n(gp), x, in_len, in)))
        return CCDH_INVALID_INPUT;
    
    if (ccn_cmp(ccdh_gp_n(gp), x, cczp_prime(gp.zp)) >= 0)
        return CCDH_SAFETY_CHECK;
    
    /* Generate the public key: y=g^x mod p */
    cczp_power(gp.zp, y, g, x);
    
    return 0;
}
示例#8
0
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);

}
示例#9
0
/* 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);
}
示例#10
0
static int ccec_mult_ws(ccec_const_cp_t cp, ccec_projective_point_t r, const cc_unit *d, ccec_const_projective_point_t s, struct ccrng_state *rng, cc_ws_t ws) {
    cc_size n=ccec_cp_n(cp);
    size_t dbitlen=ccn_bitlen(n,d);

    cc_unit *R0=ws->start;          // R0 and R1 are full points:
    cc_unit *R1=ws->start+2*n;      // X in [0..n-1] and Y in [n..2n-1]
    ws->start+=4*n;
    cc_assert((ws->start)<=ws->end); // Check that provided workspace is sufficient;

    // Check edge cases

    // Scalar d must be <= q to
    // prevent intermediary results to be the point at infinity
    // corecrypto to take care to meet this requirement
    cc_assert(ccn_cmp(n,d,cczp_prime(ccec_cp_zq(cp)))<=0); // d <= q
    ccn_sub1(n,R0,cczp_prime(ccec_cp_zq(cp)),1); // q-1
    if (dbitlen < 1) {
        ccn_clear(n, ccec_point_x(r, cp));
        ccn_clear(n, ccec_point_y(r, cp));
        ccn_clear(n, ccec_point_z(r, cp));
    } else if (dbitlen == 1) {
        // If d=1 => r=s
        ccn_set(n, ccec_point_x(r, cp), ccec_const_point_x(s, cp));
        ccn_set(n, ccec_point_y(r, cp), ccec_const_point_y(s, cp));
        ccn_set(n, ccec_point_z(r, cp), ccec_const_point_z(s, cp));
    } else if (ccn_cmp(n,d,R0)==0) {
        // If d=(q-1) => r=-s
        // Case not handle by Montgomery Ladder because R1-R0 = s.
        // On the last iteration r=R0 => R1 is equal to infinity which is not supported
        ccn_set(n, ccec_point_x(r, cp), ccec_const_point_x(s, cp));
        ccn_sub(n, ccec_point_y(r, cp), cczp_prime(cp.zp), ccec_const_point_y(s, cp));
        ccn_set(n, ccec_point_z(r, cp), ccec_const_point_z(s, cp));
    }
    else {
        // Randomize buffer to harden against cache attacks
        // TODO: scalar randomization.
        cc_unit c=1;
        if (rng) ccn_random_bits(1,&c,rng);

        // Core of the EC scalar multiplication
        cc_unit dbit; // Bit of d at index i
        cc_unit *R[2] __attribute__((aligned(16)))={R0,R1};

        XYCZdblJac(cp,R[c^1],R[c^0],s,ws);

        // Main loop
        for (unsigned long i = dbitlen - 2; i>0; --i) {
            dbit=c^(ccn_bit(d, i));
            XYCZaddC(cp,R[dbit],R[1^dbit],ws);
            XYCZadd(cp,R[dbit],R[1^dbit],ws);
            // Per Montgomery Ladder:
            // Invariably, R1 - R0 = P at this point of the loop
        }

        // Last iteration
        dbit=c^(ccn_bit(d, 0));
        XYCZaddC(cp,R[dbit],R[1^dbit],ws);
        // If d0 =      0           1
        //          R1-R0=-P     R1-R0=P
        // Therefore we can reconstruct the Z coordinate
        // To save an inversion and keep the result in Jacobian projective coordinates,
        //  we compute coefficient for X and Y.
        XYCZrecoverCoeffJac(cp,
                            ccec_point_x(r, cp),
                            ccec_point_y(r, cp),
                            ccec_point_z(r, cp),
                            R[c^1],R[c^0],
                            (int)(dbit^c),
                            s,
                            ws);
        XYCZadd(cp,R[dbit],R[1^dbit],ws);

        // Apply coefficients
        cczp_mul_ws(cp.zp,  ccec_point_x(r, cp), ccec_point_x(r, cp), &(R[c][0]), ws); // X0 * lambdaX
        cczp_mul_ws(cp.zp,  ccec_point_y(r, cp), ccec_point_y(r, cp), &(R[c][n]), ws); // Y0 * lambdaY
    }
#if CCEC_MULT_DEBUG
    ccn_lprint(n, "Result X:", ccec_point_x(r, cp));
    ccn_lprint(n, "Result Y:", ccec_point_y(r, cp));
    ccn_lprint(n, "Result Z:", ccec_point_z(r, cp));
#endif
    ws->start-=4*n;

    return 0;
}
示例#11
0
static OSStatus SecRSAPrivateKeyRawSign(SecKeyRef key, SecPadding padding,
    const uint8_t *dataToSign, size_t dataToSignLen,
    uint8_t *sig, size_t *sigLen) {

    OSStatus result = errSecParam;

    ccrsa_full_ctx_t fullkey;
    fullkey.full = key->key;

    size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
    cc_unit s[ccrsa_ctx_n(fullkey)];

    uint8_t* sBytes = (uint8_t*) s;

    require(sigLen, errOut);
    require(*sigLen >= m_size, errOut);

    switch (padding) {
        case kSecPaddingNone:
            require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(fullkey), s, dataToSignLen, dataToSign), errOut);
            require_quiet(ccn_cmp(ccrsa_ctx_n(fullkey), s, ccrsa_ctx_m(fullkey)) < 0, errOut);
            break;

        case kSecPaddingPKCS1:
        {
            // Create PKCS1 padding:
            //
            // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
            //
            const int kMinimumPadding = 1 + 1 + 8 + 1;

            require(dataToSignLen < m_size - kMinimumPadding, errOut);

            size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(fullkey)) - m_size;
            
            while (prefix_zeros--)
                *sBytes++ = 0x00;
            
            size_t pad_size = m_size - dataToSignLen;

            *sBytes++ = 0x00;
            *sBytes++ = RSA_PKCS1_PAD_SIGN;

            size_t ff_size;
            for(ff_size = pad_size - 3; ff_size > 0; --ff_size)
                *sBytes++ = 0xFF;

            *sBytes++ = 0x00;

            // Get the user data into s looking like a ccn.
            memcpy(sBytes, dataToSign, dataToSignLen);
            ccn_swap(ccrsa_ctx_n(fullkey), s);

            break;
        }
        case kSecPaddingOAEP:
            result = errSecParam;
        default:
            goto errOut;
    }

    ccrsa_priv_crypt(ccrsa_ctx_private(fullkey), s, s);

    // Pad with leading zeros to fit in modulus size
    ccn_write_uint_padded(ccrsa_ctx_n(fullkey), s, m_size, sig);
    *sigLen = m_size;

    result = errSecSuccess;

errOut:
    ccn_zero(ccrsa_ctx_n(fullkey), s);
    return result;
}
示例#12
0
static OSStatus SecRSAPublicKeyRawEncrypt(SecKeyRef key, SecPadding padding,
    const uint8_t *plainText, size_t plainTextLen,
	uint8_t *cipherText, size_t *cipherTextLen) {
    OSStatus result = errSecParam;
    ccrsa_pub_ctx_t pubkey;
    pubkey.pub = key->key;

    cc_unit s[ccrsa_ctx_n(pubkey)];
    const size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));

    require(cipherTextLen, errOut);
    require(*cipherTextLen >= m_size, errOut);

    uint8_t* sBytes = (uint8_t*) s;

    switch (padding) {
        case kSecPaddingNone:
            require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(pubkey), s, plainTextLen, plainText), errOut);
            require_quiet(ccn_cmp(ccrsa_ctx_n(pubkey), s, ccrsa_ctx_m(pubkey)) < 0, errOut);
            break;

        case kSecPaddingPKCS1:
        {
            // Create PKCS1 padding:
            //
            // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
            //
            const int kMinimumPadding = 1 + 1 + 8 + 1;

            require_quiet(plainTextLen < m_size - kMinimumPadding, errOut);

            size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(pubkey)) - m_size;
            
            while (prefix_zeros--)
                 *sBytes++ = 0x00;

           size_t pad_size = m_size - plainTextLen;

            *sBytes++ = 0x00;
            *sBytes++ = RSA_PKCS1_PAD_ENCRYPT;

            ccrng_generate(ccrng_seckey, pad_size - 3, sBytes);
            // Remove zeroes from the random pad

            const uint8_t* sEndOfPad = sBytes + (pad_size - 3);
            while (sBytes < sEndOfPad)
            {
                if (*sBytes == 0x00)
                    *sBytes = 0xFF; // Michael said 0xFF was good enough.

                ++sBytes;
            }

            *sBytes++ = 0x00;

            memcpy(sBytes, plainText, plainTextLen);

            ccn_swap(ccrsa_ctx_n(pubkey), s);
            break;
        }
        case kSecPaddingOAEP:
        {
            const struct ccdigest_info* di = ccsha1_di();

            const size_t encodingOverhead = 2 + 2 * di->output_size;

            require_action(m_size > encodingOverhead, errOut, result = errSecParam);
            require_action_quiet(plainTextLen < m_size - encodingOverhead, errOut, result = errSSLCrypto);

            require_noerr_action(ccrsa_oaep_encode(di,
                                                   ccrng_seckey,
                                                   m_size, s,
                                                   plainTextLen, plainText), errOut, result = errSecInternal);
           break;
        }
        default:
            goto errOut;
    }


    ccrsa_pub_crypt(pubkey, s, s);

    ccn_write_uint_padded(ccrsa_ctx_n(pubkey), s, m_size, cipherText);
    *cipherTextLen = m_size;

    result = errSecSuccess;

errOut:
    ccn_zero(ccrsa_ctx_n(pubkey), s);
    return result;
}