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; }
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; }
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 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); } }
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; }
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; }
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"); }
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; }
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]); }
/* 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 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 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; }
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; }