int rsa_verify (const uint8_t *pubkey, const uint8_t *hash, const uint8_t *sig) { int r; rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); rsa_ctx.len = KEY_CONTENT_LEN; mpi_lset (&rsa_ctx.E, 0x10001); mpi_read_binary (&rsa_ctx.N, pubkey, KEY_CONTENT_LEN); DEBUG_INFO ("RSA verify..."); r = rsa_pkcs1_verify (&rsa_ctx, RSA_PUBLIC, SIG_RSA_SHA256, 32, hash, sig); rsa_free (&rsa_ctx); if (r < 0) { DEBUG_INFO ("fail:"); DEBUG_SHORT (r); return r; } else { DEBUG_INFO ("verified.\r\n"); return 0; } }
/* * Create own private value X and export G^X */ int dhm_make_public (dhm_context * ctx, int x_size, unsigned char* output, int olen, int (*f_rng) (void* ), void* p_rng) { int ret, i, n; unsigned char* p; if (ctx == NULL || olen < 1 || olen > ctx->len) return (POLARSSL_ERR_DHM_BAD_INPUT_DATA); /* * generate X and calculate GX = G^X mod P */ n = x_size / sizeof (t_int); MPI_CHK (mpi_grow (&ctx->X, n)); MPI_CHK (mpi_lset (&ctx->X, 0)); n = x_size - 1; p = (unsigned char *) ctx->X.p; for (i = 0; i < n; i++) *p++ = (unsigned char) f_rng (p_rng); while (mpi_cmp_mpi (&ctx->X, &ctx->P) >= 0) mpi_shift_r (&ctx->X, 1); MPI_CHK (mpi_exp_mod (&ctx->GX, &ctx->G, &ctx->X, &ctx->P, &ctx->RP)); MPI_CHK (mpi_write_binary (&ctx->GX, output, olen)); cleanup: if (ret != 0) return (POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED | ret); return (0); }
/* * Generate an RSA keypair */ int rsa_gen_key( rsa_context *ctx, int nbits, int exponent, ulong (*rng_fn)(void *), void *rng_st ) { int ret; mpi P1, Q1, H, G; mpi_init( &P1, &Q1, &H, &G, NULL ); memset( ctx, 0, sizeof( rsa_context ) ); /* * find primes P and Q with Q < P so that: * GCD( E, (P-1)*(Q-1) ) == 1 */ CHK( mpi_lset( &ctx->E, exponent ) ); nbits >>= 1; do { CHK( mpi_gen_prime( &ctx->P, nbits, 0, rng_fn, rng_st ) ); CHK( mpi_gen_prime( &ctx->Q, nbits, 0, rng_fn, rng_st ) ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mpi_swap( &ctx->P, &ctx->Q ); CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); CHK( mpi_gcd( &G, &ctx->E, &H ) ); } while( mpi_cmp_int( &G, 1 ) != 0 ); /* * D = E^-1 mod ((P-1)*(Q-1)) * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); ctx->len = ( mpi_size( &ctx->N ) + 7 ) >> 3; cleanup: mpi_free( &P1, &Q1, &H, &G, NULL ); if( ret != 0 ) { rsa_free( ctx ); return( ERR_RSA_KEYGEN_FAILED | ret ); } return( 0 ); }
/* Generate an RSA keypair */ int rsa_gen_key(rsa_context *ctx, int nbits, int exponent) { mpi P1, Q1, H, G; int ret; if (ctx->f_rng == NULL || nbits < 128 || exponent < 3) { return EST_ERR_RSA_BAD_INPUT_DATA; } mpi_init(&P1, &Q1, &H, &G, NULL); /* find primes P and Q with Q < P so that: GCD( E, (P-1)*(Q-1) ) == 1 */ MPI_CHK(mpi_lset(&ctx->E, exponent)); do { MPI_CHK(mpi_gen_prime(&ctx->P, (nbits + 1) >> 1, 0, ctx->f_rng, ctx->p_rng)); MPI_CHK(mpi_gen_prime(&ctx->Q, (nbits + 1) >> 1, 0, ctx->f_rng, ctx->p_rng)); if (mpi_cmp_mpi(&ctx->P, &ctx->Q) < 0) { mpi_swap(&ctx->P, &ctx->Q); } if (mpi_cmp_mpi(&ctx->P, &ctx->Q) == 0) { continue; } MPI_CHK(mpi_mul_mpi(&ctx->N, &ctx->P, &ctx->Q)); if (mpi_msb(&ctx->N) != nbits) { continue; } MPI_CHK(mpi_sub_int(&P1, &ctx->P, 1)); MPI_CHK(mpi_sub_int(&Q1, &ctx->Q, 1)); MPI_CHK(mpi_mul_mpi(&H, &P1, &Q1)); MPI_CHK(mpi_gcd(&G, &ctx->E, &H)); } while (mpi_cmp_int(&G, 1) != 0); /* D = E^-1 mod ((P-1)*(Q-1)) DP = D mod (P - 1) DQ = D mod (Q - 1) QP = Q^-1 mod P */ MPI_CHK(mpi_inv_mod(&ctx->D, &ctx->E, &H)); MPI_CHK(mpi_mod_mpi(&ctx->DP, &ctx->D, &P1)); MPI_CHK(mpi_mod_mpi(&ctx->DQ, &ctx->D, &Q1)); MPI_CHK(mpi_inv_mod(&ctx->QP, &ctx->Q, &ctx->P)); ctx->len = (mpi_msb(&ctx->N) + 7) >> 3; cleanup: mpi_free(&G, &H, &Q1, &P1, NULL); if (ret != 0) { rsa_free(ctx); return EST_ERR_RSA_KEY_GEN_FAILED | ret; } return 0; }
/* * Setup and write the ServerKeyExchange parameters */ int dhm_make_params( dhm_context *ctx, int x_size, unsigned char *output, int *olen, int (*f_rng)(void *), void *p_rng ) { int i, ret, n, n1, n2, n3; unsigned char *p; /* * generate X and calculate GX = G^X mod P */ n = x_size / sizeof( t_int ); MPI_CHK( mpi_grow( &ctx->X, n ) ); MPI_CHK( mpi_lset( &ctx->X, 0 ) ); n = x_size >> 3; p = (unsigned char *) ctx->X.p; for( i = 0; i < n; i++ ) *p++ = (unsigned char) f_rng( p_rng ); while( mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) mpi_shift_r( &ctx->X, 1 ); MPI_CHK( mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, &ctx->P , &ctx->RP ) ); /* * export P, G, GX */ #define DHM_MPI_EXPORT(X,n) \ MPI_CHK( mpi_write_binary( X, p + 2, n ) ); \ *p++ = (unsigned char)( n >> 8 ); \ *p++ = (unsigned char)( n ); p += n; n1 = mpi_size( &ctx->P ); n2 = mpi_size( &ctx->G ); n3 = mpi_size( &ctx->GX ); p = output; DHM_MPI_EXPORT( &ctx->P , n1 ); DHM_MPI_EXPORT( &ctx->G , n2 ); DHM_MPI_EXPORT( &ctx->GX, n3 ); *olen = p - output; ctx->len = n1; cleanup: if( ret != 0 ) return( ret | XYSSL_ERR_DHM_MAKE_PARAMS_FAILED ); return( 0 ); }
int rsa_decrypt (const uint8_t *input, uint8_t *output, int msg_len, struct key_data *kd) { mpi P1, Q1, H; int r; int output_len; DEBUG_INFO ("RSA decrypt:"); DEBUG_WORD ((uint32_t)&output_len); mpi_init (&P1, &Q1, &H, NULL); rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); rsa_ctx.len = msg_len; DEBUG_WORD (msg_len); mpi_lset (&rsa_ctx.E, 0x10001); mpi_read_binary (&rsa_ctx.P, &kd->data[0], KEY_CONTENT_LEN / 2); mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], KEY_CONTENT_LEN / 2); #if 0 /* Using CRT, we don't use N */ mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q); #endif mpi_sub_int (&P1, &rsa_ctx.P, 1); mpi_sub_int (&Q1, &rsa_ctx.Q, 1); mpi_mul_mpi (&H, &P1, &Q1); mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H); mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1); mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1); mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P); mpi_free (&P1, &Q1, &H, NULL); DEBUG_INFO ("RSA decrypt ..."); r = rsa_pkcs1_decrypt (&rsa_ctx, RSA_PRIVATE, &output_len, input, output, MAX_RES_APDU_DATA_SIZE); rsa_free (&rsa_ctx); if (r < 0) { DEBUG_INFO ("fail:"); DEBUG_SHORT (r); return r; } else { res_APDU_size = output_len; DEBUG_INFO ("done.\r\n"); GPG_SUCCESS (); return 0; } }
int rsa_sign (const uint8_t *raw_message, uint8_t *output, int msg_len, struct key_data *kd) { mpi P1, Q1, H; int r; unsigned char temp[RSA_SIGNATURE_LENGTH]; mpi_init (&P1, &Q1, &H, NULL); rsa_init (&rsa_ctx, RSA_PKCS_V15, 0); rsa_ctx.len = KEY_CONTENT_LEN; mpi_lset (&rsa_ctx.E, 0x10001); mpi_read_binary (&rsa_ctx.P, &kd->data[0], rsa_ctx.len / 2); mpi_read_binary (&rsa_ctx.Q, &kd->data[KEY_CONTENT_LEN/2], rsa_ctx.len / 2); #if 0 /* Using CRT, we don't use N */ mpi_mul_mpi (&rsa_ctx.N, &rsa_ctx.P, &rsa_ctx.Q); #endif mpi_sub_int (&P1, &rsa_ctx.P, 1); mpi_sub_int (&Q1, &rsa_ctx.Q, 1); mpi_mul_mpi (&H, &P1, &Q1); mpi_inv_mod (&rsa_ctx.D , &rsa_ctx.E, &H); mpi_mod_mpi (&rsa_ctx.DP, &rsa_ctx.D, &P1); mpi_mod_mpi (&rsa_ctx.DQ, &rsa_ctx.D, &Q1); mpi_inv_mod (&rsa_ctx.QP, &rsa_ctx.Q, &rsa_ctx.P); mpi_free (&P1, &Q1, &H, NULL); DEBUG_INFO ("RSA sign..."); r = rsa_pkcs1_sign (&rsa_ctx, RSA_PRIVATE, SIG_RSA_RAW, msg_len, raw_message, temp); memcpy (output, temp, RSA_SIGNATURE_LENGTH); rsa_free (&rsa_ctx); if (r < 0) { DEBUG_INFO ("fail:"); DEBUG_SHORT (r); return r; } else { res_APDU_size = RSA_SIGNATURE_LENGTH; DEBUG_INFO ("done.\r\n"); GPG_SUCCESS (); return 0; } }
/* * Verify sanity of parameter with regards to P * * Parameter should be: 2 <= public_param <= P - 2 * * For more information on the attack, see: * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 */ static int dhm_check_range( const mpi *param, const mpi *P ) { mpi L, U; int ret = POLARSSL_ERR_DHM_BAD_INPUT_DATA; mpi_init( &L ); mpi_init( &U ); mpi_lset( &L, 2 ); mpi_sub_int( &U, P, 2 ); if( mpi_cmp_mpi( param, &L ) >= 0 && mpi_cmp_mpi( param, &U ) <= 0 ) { ret = 0; } mpi_free( &L ); mpi_free( &U ); return( ret ); }
/* * Generate an RSA keypair */ int rsa_gen_key( rsa_context *ctx, int (*f_rng)(void *), void *p_rng, int nbits, int exponent ) { int ret; mpi P1, Q1, H, G; if( f_rng == NULL || nbits < 128 || exponent < 3 ) return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); mpi_init( &P1, &Q1, &H, &G, NULL ); /* * find primes P and Q with Q < P so that: * GCD( E, (P-1)*(Q-1) ) == 1 */ MPI_CHK( mpi_lset( &ctx->E, exponent ) ); do { MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mpi_swap( &ctx->P, &ctx->Q ); if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) continue; MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); if( mpi_msb( &ctx->N ) != nbits ) continue; MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); } while( mpi_cmp_int( &G, 1 ) != 0 ); /* * D = E^-1 mod ((P-1)*(Q-1)) * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; cleanup: mpi_free( &G, &H, &Q1, &P1, NULL ); if( ret != 0 ) { rsa_free( ctx ); return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret ); } return( 0 ); }
/* * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. * WARNING: the resulting group should only be used with * pk_group_id_from_specified(), since its base point may not be set correctly * if it was encoded compressed. * * SpecifiedECDomain ::= SEQUENCE { * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), * fieldID FieldID {{FieldTypes}}, * curve Curve, * base ECPoint, * order INTEGER, * cofactor INTEGER OPTIONAL, * hash HashAlgorithm OPTIONAL, * ... * } * * We only support prime-field as field type, and ignore hash and cofactor. */ static int pk_group_from_specified( const asn1_buf *params, ecp_group *grp ) { int ret; unsigned char *p = params->p; const unsigned char * const end = params->p + params->len; const unsigned char *end_field, *end_curve; size_t len; int ver; /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ if( ( ret = asn1_get_int( &p, end, &ver ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( ver < 1 || ver > 3 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); /* * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field * fieldType FIELD-ID.&id({IOSet}), * parameters FIELD-ID.&Type({IOSet}{@fieldType}) * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ret ); end_field = p + len; /* * FIELD-ID ::= TYPE-IDENTIFIER * FieldTypes FIELD-ID ::= { * { Prime-p IDENTIFIED BY prime-field } | * { Characteristic-two IDENTIFIED BY characteristic-two-field } * } * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } */ if( ( ret = asn1_get_tag( &p, end_field, &len, ASN1_OID ) ) != 0 ) return( ret ); if( len != OID_SIZE( OID_ANSI_X9_62_PRIME_FIELD ) || memcmp( p, OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) { return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); } p += len; /* Prime-p ::= INTEGER -- Field of size p. */ if( ( ret = asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); grp->pbits = mpi_msb( &grp->P ); if( p != end_field ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); /* * Curve ::= SEQUENCE { * a FieldElement, * b FieldElement, * seed BIT STRING OPTIONAL * -- Shall be present if used in SpecifiedECDomain * -- with version equal to ecdpVer2 or ecdpVer3 * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) return( ret ); end_curve = p + len; /* * FieldElement ::= OCTET STRING * containing an integer in the case of a prime field */ if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || ( ret = mpi_read_binary( &grp->A, p, len ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } p += len; if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_OCTET_STRING ) ) != 0 || ( ret = mpi_read_binary( &grp->B, p, len ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } p += len; /* Ignore seed BIT STRING OPTIONAL */ if( ( ret = asn1_get_tag( &p, end_curve, &len, ASN1_BIT_STRING ) ) == 0 ) p += len; if( p != end_curve ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); /* * ECPoint ::= OCTET STRING */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( ( ret = ecp_point_read_binary( grp, &grp->G, ( const unsigned char *) p, len ) ) != 0 ) { /* * If we can't read the point because it's compressed, cheat by * reading only the X coordinate and the parity bit of Y. */ if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE || ( p[0] != 0x02 && p[0] != 0x03 ) || len != mpi_size( &grp->P ) + 1 || mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || mpi_lset( &grp->G.Z, 1 ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); } } p += len; /* * order INTEGER */ if( ( ret = asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); grp->nbits = mpi_msb( &grp->N ); /* * Allow optional elements by purposefully not enforcing p == end here. */ return( 0 ); }
result_t X509Req::sign(const char *issuer, PKey_base *key, v8::Local<v8::Object> opts, obj_ptr<X509Cert_base> &retVal, exlib::AsyncEvent *ac) { result_t hr; bool priv; hr = key->isPrivate(priv); if (hr < 0) return hr; if (!priv) return CHECK_ERROR(CALL_E_INVALIDARG); int ret; std::string subject; pk_context *pk; int32_t hash; std::string buf; obj_ptr<X509Cert> cert; if (!ac) { mpi serial; v8::Local<v8::Value> v; x509write_crt_init(&m_crt); hr = GetConfigValue(opts, "hash", hash); if (hr == CALL_E_PARAMNOTOPTIONAL) hash = m_csr.sig_md; else if (hr < 0) goto exit; if (hash < POLARSSL_MD_MD2 || hash > POLARSSL_MD_RIPEMD160) { hr = CALL_E_INVALIDARG; goto exit; } x509write_crt_set_md_alg(&m_crt, POLARSSL_MD_SHA1); v = opts->Get(v8::String::NewFromUtf8(isolate, "serial", v8::String::kNormalString, 6)); if (!IsEmpty(v)) { v8::String::Utf8Value str(v); if (!*str) { hr = CHECK_ERROR(_ssl::setError(POLARSSL_ERR_MPI_BAD_INPUT_DATA)); goto exit; } mpi_init(&serial); ret = mpi_read_string(&serial, 10, *str); if (ret != 0) { mpi_free(&serial); hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } } else { mpi_init(&serial); mpi_lset(&serial, 1); } ret = x509write_crt_set_serial(&m_crt, &serial); if (ret != 0) { mpi_free(&serial); hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } mpi_free(&serial); date_t d1, d2; std::string s1, s2; hr = GetConfigValue(opts, "notBefore", d1); if (hr == CALL_E_PARAMNOTOPTIONAL) d1.now(); else if (hr < 0) goto exit; d1.toX509String(s1); hr = GetConfigValue(opts, "notAfter", d2); if (hr == CALL_E_PARAMNOTOPTIONAL) { d2 = d1; d2.add(1, date_t::_YEAR); } else if (hr < 0) goto exit; d2.toX509String(s2); ret = x509write_crt_set_validity(&m_crt, s1.c_str(), s2.c_str()); if (ret != 0) { hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } bool is_ca = false; hr = GetConfigValue(opts, "ca", is_ca); if (hr < 0 && hr != CALL_E_PARAMNOTOPTIONAL) goto exit; int32_t pathlen = -1; hr = GetConfigValue(opts, "pathlen", pathlen); if (hr < 0 && hr != CALL_E_PARAMNOTOPTIONAL) goto exit; if (pathlen < -1 || pathlen > 127) { hr = CALL_E_INVALIDARG; goto exit; } ret = x509write_crt_set_basic_constraints(&m_crt, is_ca ? 1 : 0, pathlen); if (ret != 0) { hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } int key_usage = parseString(opts->Get(v8::String::NewFromUtf8(isolate, "usage", v8::String::kNormalString, 5)), X509Cert::g_usages); if (key_usage < 0) { hr = key_usage; goto exit; } else if (key_usage) { ret = x509write_crt_set_key_usage(&m_crt, key_usage); if (ret != 0) { hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } } int cert_type = parseString(opts->Get(v8::String::NewFromUtf8(isolate, "type", v8::String::kNormalString, 4)), X509Cert::g_types); if (cert_type < 0) { hr = cert_type; goto exit; } else if (cert_type) { ret = x509write_crt_set_ns_cert_type(&m_crt, cert_type); if (ret != 0) { hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } } return CHECK_ERROR(CALL_E_NOSYNC); } pk = &((PKey *)key)->m_key; x509write_crt_set_subject_key(&m_crt, &m_csr.pk); x509write_crt_set_issuer_key(&m_crt, pk); hr = X509Req::get_subject(subject); if (hr < 0) goto exit; ret = x509write_crt_set_subject_name(&m_crt, subject.c_str()); if (ret != 0) { hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } ret = x509write_crt_set_issuer_name(&m_crt, issuer); if (ret != 0) { hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } ret = x509write_crt_set_subject_key_identifier(&m_crt); if (ret != 0) { hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } ret = x509write_crt_set_authority_key_identifier(&m_crt); if (ret != 0) { hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } buf.resize(pk_get_size(pk) * 8 + 128); ret = x509write_crt_pem(&m_crt, (unsigned char *)&buf[0], buf.length(), ctr_drbg_random, &g_ssl.ctr_drbg); if (ret < 0) { hr = CHECK_ERROR(_ssl::setError(ret)); goto exit; } cert = new X509Cert(); hr = cert->load(buf.c_str()); if (hr < 0) goto exit; retVal = cert; exit: x509write_crt_free(&m_crt); return hr; }