Exemple #1
0
static size_t ccn_write_radix_size(cc_size n, const cc_unit *s,
                                   unsigned radix) {
    if (ccn_is_zero(n, s)) {
        return 1;
    }

    /* digs is the digit count */
    cc_unit uradix[1] = { radix };
    size_t k = ccn_bitlen(1, uradix) - 1;
    size_t l = ccn_trailing_zeros(1, uradix);
    if (k == l) {
        /* Radix is 2**k. */
        return (ccn_bitlen(n, s) + k - 1) / k;
    } else {
        size_t size = 0;
        n = ccn_n(n, s);
        cc_unit t[n];
        ccn_set(n, t, s);
        cc_unit v[1];
        while (n) {
            ccn_div1(n, t, v, t, radix);
            n = ccn_n(n, t);
            ++size;
        }
        return size;
    }
}
Exemple #2
0
CCCryptorStatus
CCRSACryptorCreateFromData( CCRSAKeyType keyType, uint8_t *modulus, size_t modulusLength, 
                            uint8_t *exponent, size_t exponentLength,
                            uint8_t *p, size_t pLength, uint8_t *q, size_t qLength,
                            CCRSACryptorRef *ref)
{
    CCCryptorStatus retval = kCCSuccess;
	CCRSACryptor *rsaKey = NULL;
    size_t n = ccn_nof_size(modulusLength);
    cc_unit m[n];
    
    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
    __Require_Action(ccn_read_uint(n, m, modulusLength, modulus) == 0, errOut, retval = kCCParamError);
    size_t nbits = ccn_bitlen(n, m);

    __Require_Action((rsaKey = ccMallocRSACryptor(nbits, keyType)) != NULL, errOut, retval = kCCMemoryFailure);

    __Require_Action(ccn_read_uint(n, ccrsa_ctx_m(rsaKey->fk), modulusLength, modulus) == 0, errOut, retval = kCCParamError);
    __Require_Action(ccn_read_uint(n, ccrsa_ctx_e(rsaKey->fk), exponentLength, exponent) == 0, errOut, retval = kCCParamError);
    cczp_init(ccrsa_ctx_zm(rsaKey->fk));
    rsaKey->keySize = ccn_bitlen(n, ccrsa_ctx_m(rsaKey->fk));

	switch(keyType) {
		case ccRSAKeyPublic:
            rsaKey->keyType = ccRSAKeyPublic;
            break;
		
		case ccRSAKeyPrivate: {
            ccrsa_priv_ctx_t privk = ccrsa_ctx_private(rsaKey->fk);
            size_t psize = ccn_nof_size(pLength);
            size_t qsize = ccn_nof_size(qLength);

            
            CCZP_N(ccrsa_ctx_private_zp(privk)) = psize;
            __Require_Action(ccn_read_uint(psize, CCZP_PRIME(ccrsa_ctx_private_zp(privk)), pLength, p) == 0, errOut, retval = kCCParamError);
            CCZP_N(ccrsa_ctx_private_zq(privk)) = qsize;
            __Require_Action(ccn_read_uint(qsize, CCZP_PRIME(ccrsa_ctx_private_zq(privk)), qLength, q) == 0, errOut, retval = kCCParamError);

            ccrsa_crt_makekey(ccrsa_ctx_zm(rsaKey->fk), ccrsa_ctx_e(rsaKey->fk), ccrsa_ctx_d(rsaKey->fk),
                              ccrsa_ctx_private_zp(privk),
                              ccrsa_ctx_private_dp(privk), ccrsa_ctx_private_qinv(privk),
                              ccrsa_ctx_private_zq(privk), ccrsa_ctx_private_dq(privk));
            
            rsaKey->keyType = ccRSAKeyPrivate;

       		break;
        }
		
		default:
            retval = kCCParamError;
			goto errOut;
	}
	*ref = rsaKey;
	return kCCSuccess;
	
errOut:
	if(rsaKey) ccRSACryptorClear(rsaKey);
	return retval;
}
Exemple #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);
    }
}
// Key is expected to be in PKCS #1 format
cc_size ccder_decode_rsa_pub_n(const uint8_t *der, const uint8_t *der_end) {
    cc_size n = ccn_nof(8192);
    cc_unit m[n];
    if((der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &der_end, der, der_end)) == NULL) return 0;
    if((der = ccder_decode_uint(n, m, der, der_end)) == NULL) return 0;
    return ccn_nof(ccn_bitlen(n, m));
}
cc_size ccder_decode_rsa_priv_n(const uint8_t *der, const uint8_t *der_end) {
	cc_unit version_0[ccn_nof(1)] = {0x00};
    cc_size n = ccn_nof(8192);
    cc_unit m[n];
    if((der = ccder_decode_constructed_tl(CCDER_CONSTRUCTED_SEQUENCE, &der_end, der, der_end)) == NULL) return 0;
    if((der = ccder_decode_uint(1, version_0, der, der_end)) == NULL) return 0;
    if(version_0[0] != 0) return 0;
    if((der = ccder_decode_uint(n, m, der, der_end)) == NULL) return 0;
    return ccn_nof(ccn_bitlen(n, m));
}
Exemple #6
0
static void ccn_div1(cc_size n, cc_unit *q, cc_unit *r, const cc_unit *s, cc_unit v) {
    if (n == 0) {
        *r = 0;
        return;
    }

    size_t k = ccn_bitlen(1, &v) - 1;
    size_t l = ccn_trailing_zeros(1, &v);
    if (k == l) {
        /* Divide by power of 2, remainder in *r. */
        *r = s[0] & (v - 1);
        ccn_shift_right(n, q, s, k);
    } else {
        ccn_divn(n, q, r, s, 1, &v);
    }
}
Exemple #7
0
void ccz_lsr(ccz *r, const ccz *s, size_t k) {
    size_t l = ccn_bitlen(ccz_n(s), s->u);
    if (l <= k) {
        ccz_zero(r);
    } else {
        cc_size kn = k / CCN_UNIT_BITS;
        l -= k;
        k &= (CCN_UNIT_BITS - 1);
        ccz_set_sign(r, ccz_sign(s));
        ccz_set_capacity(r, ccz_n(s) - kn);
        if (k) {
            ccn_shift_right(ccz_n(s) - kn, r->u, s->u + kn, k);
        } else if (kn || r != s) {
            /* Forward copy, safe to use ccn_set(). */
            ccn_set(ccz_n(s) - kn, r->u, s->u + kn);
        }
        ccz_set_n(r, ccn_nof(l));
    }
}
Exemple #8
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);
}
// verify the signature in sig. The original (hash of the message) message is in digest
int ccrsa_verify_pss(ccrsa_pub_ctx_t key,
                      const struct ccdigest_info* di, const struct ccdigest_info* MgfDi,
                      size_t digestSize, const uint8_t *digest,
                      size_t sigSize, const uint8_t *sig,
                      size_t saltSize, bool *valid)
{
    const cc_size modBits =ccn_bitlen(ccrsa_ctx_n(key), ccrsa_ctx_m(key));
    const cc_size modBytes = cc_ceiling(modBits, 8);
    const cc_size emBits = modBits-1; //as defined in §8.1.1
    const cc_size emSize = cc_ceiling(emBits, 8);
    *valid = false;
    int rc=0;
    
    //1.
    if(modBytes!= sigSize)  return CCRSA_INVALID_INPUT;
    if(digestSize !=  di->output_size) return CCRSA_INVALID_INPUT;

    //2.
    const cc_size modWords=ccrsa_ctx_n(key);
    cc_unit EM[modWords];  //EM islarge enough to fit sig variable
    
    //2.a read sig to tmp array and make sure it fits
    cc_require_action(ccn_read_uint(modWords, EM, sigSize, sig)==0,errOut,rc=CCRSA_INVALID_INPUT);

    //2.b
    cc_require((rc=ccrsa_pub_crypt(key, EM, EM))==0,errOut);
    
    //2.c
    ccn_swap(modWords, EM);

    //3
    const size_t ofs = modWords*sizeof(cc_unit)-emSize;
    cc_assert(ofs<=sizeof(cc_unit)); //make sure sizes are consistent and we don't overrun buffers.
    rc|= ccrsa_emsa_pss_decode(di, MgfDi, saltSize, digestSize,  digest, emBits, (uint8_t *) EM+ofs);

    *valid = (rc==0)?true:false;
errOut:
    return rc;
}
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;
}
Exemple #11
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;
}
Exemple #12
0
static inline size_t
ccRSAkeysize(CCRSACryptor *cryptor) {
    return ccn_bitlen(ccrsa_ctx_n(cryptor->fk), ccrsa_ctx_m(cryptor->fk));
}