static int ccrsa_priv_init(ccrsa_priv_ctx_t privkey, size_t p_size, const uint8_t* p, size_t q_size, const uint8_t* q, size_t dp_size, const uint8_t* dp, size_t dq_size, const uint8_t* dq, size_t qinv_size, const uint8_t* qinv) { int result = -1; const cc_size np = cczp_n(ccrsa_ctx_private_zp(privkey)); cc_size nq = cczp_n(ccrsa_ctx_private_zq(privkey)); if (ccn_read_uint(np, CCZP_PRIME(ccrsa_ctx_private_zp(privkey)), p_size, p)) goto errOut; cczp_init(ccrsa_ctx_private_zp(privkey)); if (ccn_read_uint(np, ccrsa_ctx_private_dp(privkey), dp_size, dp)) goto errOut; if (ccn_read_uint(np, ccrsa_ctx_private_qinv(privkey), qinv_size, qinv)) goto errOut; if (ccn_read_uint(nq, CCZP_PRIME(ccrsa_ctx_private_zq(privkey)), q_size, q)) goto errOut; nq = ccn_n(nq, cczp_prime(ccrsa_ctx_private_zq(privkey))); CCZP_N(ccrsa_ctx_private_zq(privkey)) = nq; cczp_init(ccrsa_ctx_private_zq(privkey)); if (ccn_read_uint(nq, ccrsa_ctx_private_dq(privkey), dq_size, dq)) goto errOut; result = 0; errOut: return result; }
void cczp_mul_ws(cczp_const_t zp, cc_unit *t, const cc_unit *x, const cc_unit *y, cc_ws_t ws) { //ccn_lprint(cczp_n(zp),"x: ",x); //ccn_lprint(cczp_n(zp),"y: ",y); cc_unit *tbig=ws->start; ws->start+=(2 * cczp_n(zp)); ccn_mul_ws(cczp_n(zp), tbig, x, y, ws); //ccn_lprint(2*cczp_n(zp),"tbig: ",tbig); zp.zp->mod_prime(zp.zp, t, tbig, ws); ws->start-=(2 * cczp_n(zp)); }
void cczp_div2(cczp_const_short_t zp, cc_unit *r, const cc_unit *x) { if (x[0] & 1) { /* x is odd r = (x + p) >> 1 */ cc_unit carry = ccn_add(cczp_n(zp), r, x, cczp_prime(zp)); ccn_shift_right(cczp_n(zp), r, r, 1); r[cczp_n(zp) - 1] |= carry << (CCN_UNIT_BITS - 1); } else { /* x is even r = x >> 1 */ ccn_shift_right(cczp_n(zp), r, x, 1); } }
void ccz_invmod(ccz *r, const ccz *s, const ccz *t) { ccz_set_sign(r, 1); ccz_set_capacity(r, ccz_n(t)); ccz_zp_decl(t, zt); cc_unit u[cczp_n(zt)]; cczp_modn(zt, u, ccz_n(s), s->u); cczp_mod_inv_slow(zt, r->u, u); ccz_set_n(r, ccn_n(cczp_n(zt), r->u)); }
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; }
size_t ccder_encode_rsa_priv_size(const ccrsa_full_ctx_t key) { ccrsa_priv_ctx_t privk = ccrsa_ctx_private(key); cc_size n = ccrsa_ctx_n(key); cc_unit version_0[ccn_nof(1)] = {0x00}; return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE, ccder_sizeof_integer(ccn_nof(1), version_0) + ccder_sizeof_integer(n, ccrsa_ctx_m(key)) + ccder_sizeof_integer(n, ccrsa_ctx_e(key)) + ccder_sizeof_integer(n, ccrsa_ctx_d(key)) + ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zp(privk)), cczp_prime(ccrsa_ctx_private_zp(privk))) + ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zq(privk)), cczp_prime(ccrsa_ctx_private_zq(privk))) + ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zp(privk)), ccrsa_ctx_private_dp(privk)) + ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zq(privk)), ccrsa_ctx_private_dq(privk)) + ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zp(privk)), ccrsa_ctx_private_qinv(privk)) ); }
void ccz_sqrmod(ccz *r, const ccz *s, const ccz *t) { ccz_set_sign(r, 1); ccz_set_capacity(r, CC_MAX(2 * ccz_n(s), ccz_n(t))); ccz_zp_decl(t, zt); ccn_sqr(ccz_n(s), r->u, s->u); cczp_modn(zt, r->u, 2 * ccz_n(s), r->u); ccz_set_n(r, ccn_n(cczp_n(zt), r->u)); }
/* 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); } } }
int ccrsa_get_fullkey_components(const ccrsa_full_ctx_t key, uint8_t *modulus, size_t *modulusLength, uint8_t *exponent, size_t *exponentLength, uint8_t *p, size_t *pLength, uint8_t *q, size_t *qLength) { cc_size n = ccrsa_ctx_n(key); if(ccCoreZP2pointerAndData(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))), cczp_prime(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))), p, pLength )) return -1; if(ccCoreZP2pointerAndData(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))), cczp_prime(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))), q, qLength )) return -1; if(ccCoreZP2pointerAndData(n, ccrsa_ctx_m(key), modulus, modulusLength )) return -1; if(ccCoreZP2pointerAndData(n, ccrsa_ctx_d(key), exponent, exponentLength )) return -1; return 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); }
static inline ccdh_full_ctx_t SecDH_priv(SecDHContext dh) { void *p = dh; cczp_t zp = { .u = p }; cc_size s = ccn_sizeof_n(cczp_n(zp)); ccdh_full_ctx_t priv = { .hdr = (struct ccdh_ctx_header *)(p+ccdh_gp_size(s)) }; return priv; } static inline size_t SecDH_context_size(size_t p_len) { cc_size n = ccn_nof_size(p_len); cc_size real_p_len = ccn_sizeof_n(n); size_t context_size = ccdh_gp_size(real_p_len)+ccdh_full_ctx_size(real_p_len); return context_size; }
void ccrsa_dump_full_key(ccrsa_full_ctx_t key) { ccn_cprint(ccrsa_ctx_n(key), "uint8_t m[] = ", ccrsa_ctx_m(key)); ccn_cprint(ccrsa_ctx_n(key) + 1, "uint8_t rm[] = ", cczp_recip(ccrsa_ctx_zm(key))); ccn_cprint(ccrsa_ctx_n(key), "uint8_t e[] = ", ccrsa_ctx_e(key)); ccn_cprint(ccrsa_ctx_n(key), "uint8_t d[] = ", ccrsa_ctx_d(key)); printf("cc_size np = %lu;\n", cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key)))); ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))), "uint8_t p[] = ", cczp_prime(ccrsa_ctx_private_zp(ccrsa_ctx_private(key)))); ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))) + 1, "uint8_t rp[] = ", cczp_recip(ccrsa_ctx_private_zp(ccrsa_ctx_private(key)))); printf("cc_size nq = %lu;\n", cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key)))); ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))), "uint8_t q[] = ", cczp_prime(ccrsa_ctx_private_zq(ccrsa_ctx_private(key)))); ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))) + 1, "uint8_t rq[] = ", cczp_recip(ccrsa_ctx_private_zq(ccrsa_ctx_private(key)))); ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))), "uint8_t dp[] = ", ccrsa_ctx_private_dp(ccrsa_ctx_private(key))); ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))), "uint8_t dq[] = ", ccrsa_ctx_private_dq(ccrsa_ctx_private(key))); ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))), "uint8_t qinv[] = ", ccrsa_ctx_private_qinv(ccrsa_ctx_private(key))); printf("--\n"); }
static void ccn_mod_521(cczp_const_t zp, cc_unit *r, const cc_unit *a, CC_UNUSED cc_ws_t ws) { cc_assert(cczp_n(zp) == CCN521_N); cc_unit t[CCN521_N]; cc_unit t2[CCN521_N]; cc_unit *select[2] __attribute__((aligned(16))) ={t,t2}; cc_unit borrow; #if CCN_UNIT_SIZE == 1 ccn_shift_right(CCN521_N - 1, t2, &a[CCN521_N - 1], 1); // r = a521,...,a1041 t2[CCN521_N - 1] += a[CCN521_N - 1] & CC_UNIT_C(1); t2[CCN521_N - 1] += ccn_add(CCN521_N - 1,t2,t2,a); #else ccn_shift_right(CCN521_N, t2, &a[CCN512_N], 9); // r = a521,...,a1041 t2[CCN512_N] += a[CCN512_N] & CC_UNIT_C(0x1ff); // r += (a512,...,a520)*2^512 t2[CCN512_N] += ccn_add(CCN512_N,t2,t2,a); // r += a0,...,a511 #endif borrow=ccn_sub(CCN521_N, t, t2, cczp_prime(zp)); ccn_set(CCN521_N,r,select[borrow]); }
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); }
static OSStatus ccrsa_full_decode(ccrsa_full_ctx_t fullkey, size_t pkcs1_size, const uint8_t* pkcs1) { OSStatus result = errSecParam; DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size}; DERRSAKeyPair decodedKey; require_noerr_action(DERParseSequence(&keyItem, DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs, &decodedKey, sizeof(decodedKey)), errOut, result = errSecDecode); require_noerr(ccrsa_pub_init(fullkey, decodedKey.n.length, decodedKey.n.data, decodedKey.e.length, decodedKey.e.data), errOut); ccn_read_uint(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey), decodedKey.d.length, decodedKey.d.data); { ccrsa_priv_ctx_t privkey = ccrsa_ctx_private(fullkey); CCZP_N(ccrsa_ctx_private_zp(privkey)) = ccn_nof((ccn_bitsof_n(ccrsa_ctx_n(fullkey)) / 2) + 1); CCZP_N(ccrsa_ctx_private_zq(privkey)) = cczp_n(ccrsa_ctx_private_zp(privkey)); // TODO: Actually remember decodedKey.d. require_noerr(ccrsa_priv_init(privkey, decodedKey.p.length, decodedKey.p.data, decodedKey.q.length, decodedKey.q.data, decodedKey.dp.length, decodedKey.dp.data, decodedKey.dq.length, decodedKey.dq.data, decodedKey.qInv.length, decodedKey.qInv.data), errOut); } result = errSecSuccess; errOut: return result; }
static inline ccdh_full_ctx_t vmdh_priv(struct vmdh *dh) { void *p = dh; cczp_t zp = { .u = p }; cc_size s = ccn_sizeof_n(cczp_n(zp)); ccdh_full_ctx_t priv = { .hdr = (struct ccdh_ctx_header *)(p+ccdh_gp_size(s)) }; return priv; } static uint32_t param_g = 5; static const uint8_t param_p[] = { 0xED, 0x42, 0x06, 0xE1, 0xDD, 0x09, 0x93, 0xA6, 0x81, 0xAE, 0x00, 0x0D, 0xBF, 0x84, 0x7F, 0x7D, 0x87, 0x64, 0x6B, 0x77, 0x24, 0x03, 0xB8, 0xC0, 0xDC, 0xBE, 0x5B, 0x9C, 0x8E, 0x71, 0x09, 0x24, 0x53, 0x77, 0x7F, 0x5D, 0x1A, 0xAD, 0x92, 0xD8, 0xFE, 0xCD, 0x5C, 0xB4, 0xCA, 0x09, 0x17, 0x11, 0xF3, 0x82, 0x01, 0x39, 0x4A, 0x09, 0xBA, 0x29, 0x95, 0x2B, 0xC4, 0xCC, 0x56, 0x21, 0x97, 0x13 }; static const uint8_t client_priv[] = { 0x32, 0x34, 0x73, 0x16, 0x7d, 0x79, 0xde, 0x47, 0x22, 0x93, 0xf5, 0x86, 0x47, 0xf6, 0x7f, 0x7a, 0xb6, 0x30, 0x16, 0x5b, 0xbf, 0xe1, 0x36, 0x0b, 0xb4, 0xd2, 0x84, 0x3e, 0x57, 0x5f, 0xcb, 0xc6, 0x6a, 0xae, 0x5d, 0x59, 0x4b, 0x70, 0x53, 0x22, 0xb0, 0x51, 0x89, 0x30, 0x74, 0xfc, 0x95, 0x51, 0x9c, 0xc9, 0xf7, 0xac, 0x8c, 0x37, 0xfd, 0xc1, 0x0e, 0x02, 0x6e, 0x69, 0x6c, 0xca, 0x2a, 0x95 }; static const uint8_t client_pub[] = { 0x15, 0xDF, 0x17, 0x6E, 0xB4, 0x95, 0xA7, 0x92, 0x41, 0xB6, 0xF1, 0x93, 0x19, 0xDB, 0x34, 0xF1, 0xE0, 0x0D, 0x62, 0xCD, 0x55, 0xC7, 0x0B, 0x27, 0xB7, 0x53, 0x1A, 0x28, 0x65, 0x11, 0xF0, 0xF6, 0xA6, 0xE1, 0x5B, 0x86, 0x1D, 0x67, 0x85, 0x19, 0x6D, 0xD6, 0x80, 0xFF, 0x5C, 0xEB, 0xC3, 0x2D, 0xC3, 0xCB, 0xD2, 0xD4, 0x66, 0x93, 0xF4, 0xFC, 0xF1, 0xF4, 0x8B, 0x61, 0x0F, 0x02, 0xF5, 0x19 }; static const uint8_t server_pub[] = { 0x73, 0xC5, 0xF8, 0xF8, 0xB8, 0x9C, 0xB0, 0x5F, 0xD6, 0xC6, 0x49, 0x5C, 0x70, 0xF5, 0x90, 0xB3, 0x8A, 0xD3, 0xD0, 0x12, 0x99, 0x47, 0x60, 0xC2, 0x5B, 0xF7, 0x18, 0x3A, 0x19, 0xF5, 0x01, 0xA3, 0x67, 0xBF, 0x57, 0x28, 0x7E, 0x99, 0xA8, 0xDB, 0x97, 0xA4, 0xAF, 0xF2, 0x68, 0x47, 0xAB, 0x48, 0xE3, 0x4D, 0xF2, 0x94, 0xB4, 0xCC, 0xFC, 0x0C, 0x50, 0xAD, 0xEF, 0x2E, 0x80, 0xA6, 0x20, 0x29 }; static const uint8_t pw[] = { 0x31, 0x32, 0x33, 0x34 }; static const uint8_t pw_encr[] = { 0x42, 0xd7, 0xa1, 0x08, 0x15, 0x8f, 0xdd, 0xc8, 0xe8, 0x75, 0xea, 0xa2, 0xc2, 0x20, 0x28, 0xfa }; #if 0 static void hexdump(const uint8_t *bytes, size_t len) { size_t ix; for (ix = 0; ix < len; ++ix) { printf("%02X", bytes[ix]); } printf("\n"); }
size_t SecDHGetMaxKeyLength(SecDHContext dh) { cczp_const_t zp; zp.u = (cc_unit *)dh; return ccn_sizeof_n(cczp_n(zp)); }
void cczp_mul(cczp_const_t zp, cc_unit *t, const cc_unit *x, const cc_unit *y) { CC_DECL_WORKSPACE(ws,CCZP_MUL_WORKSPACE_N(cczp_n(zp))); cczp_mul_ws(zp,t,x,y,ws); CC_FREE_WORKSPACE(ws); }
static CFDataRef SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_full_ctx_t fullkey) { ccrsa_priv_ctx_t privkey = ccrsa_ctx_private(fullkey); const cc_size np = cczp_n(ccrsa_ctx_private_zp(privkey)); const cc_size nq = cczp_n(ccrsa_ctx_private_zq(privkey)); size_t m_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey)); size_t e_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_e(fullkey)); size_t d_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey)); size_t p_size = ccn_write_int_size(np, cczp_prime(ccrsa_ctx_private_zp(privkey))); size_t q_size = ccn_write_int_size(nq, cczp_prime(ccrsa_ctx_private_zq(privkey))); size_t dp_size = ccn_write_int_size(np, ccrsa_ctx_private_dp(privkey)); size_t dq_size = ccn_write_int_size(nq, ccrsa_ctx_private_dq(privkey)); size_t qinv_size = ccn_write_int_size(np, ccrsa_ctx_private_qinv(privkey)); const size_t seq_size = 3 + DERLengthOfItem(ASN1_INTEGER, m_size) + DERLengthOfItem(ASN1_INTEGER, e_size) + DERLengthOfItem(ASN1_INTEGER, d_size) + DERLengthOfItem(ASN1_INTEGER, p_size) + DERLengthOfItem(ASN1_INTEGER, q_size) + DERLengthOfItem(ASN1_INTEGER, dp_size) + DERLengthOfItem(ASN1_INTEGER, dq_size) + DERLengthOfItem(ASN1_INTEGER, qinv_size); const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size); CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size); if (pkcs1 == NULL) return NULL; CFDataSetLength(pkcs1, result_size); uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1); *bytes++ = ASN1_CONSTR_SEQUENCE; DERSize itemLength = 4; DEREncodeLength(seq_size, bytes, &itemLength); bytes += itemLength; *bytes++ = ASN1_INTEGER; *bytes++ = 0x01; *bytes++ = 0x00; ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey), m_size, &bytes); ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_e(fullkey), e_size, &bytes); ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey), d_size, &bytes); ccasn_encode_int(np, cczp_prime(ccrsa_ctx_private_zp(privkey)), p_size, &bytes); ccasn_encode_int(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)), q_size, &bytes); ccasn_encode_int(np, ccrsa_ctx_private_dp(privkey), dp_size, &bytes); ccasn_encode_int(nq, ccrsa_ctx_private_dq(privkey), dq_size, &bytes); ccasn_encode_int(np, ccrsa_ctx_private_qinv(privkey), qinv_size, &bytes); return pkcs1; }