/* * Verify a signature with options */ int pk_verify_ext( pk_type_t type, const void *options, pk_context *ctx, md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ) { if( ctx == NULL || ctx->pk_info == NULL ) return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); if( ! pk_can_do( ctx, type ) ) return( POLARSSL_ERR_PK_TYPE_MISMATCH ); if( type == POLARSSL_PK_RSASSA_PSS ) { #if defined(POLARSSL_RSA_C) && defined(POLARSSL_PKCS1_V21) int ret; const pk_rsassa_pss_options *pss_opts; if( options == NULL ) return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); pss_opts = (const pk_rsassa_pss_options *) options; if( sig_len < pk_get_len( ctx ) ) return( POLARSSL_ERR_RSA_VERIFY_FAILED ); ret = rsa_rsassa_pss_verify_ext( pk_rsa( *ctx ), NULL, NULL, RSA_PUBLIC, md_alg, hash_len, hash, pss_opts->mgf1_hash_id, pss_opts->expected_salt_len, sig ); if( ret != 0 ) return( ret ); if( sig_len > pk_get_len( ctx ) ) return( POLARSSL_ERR_PK_SIG_LEN_MISMATCH ); return( 0 ); #else return( POLARSSL_ERR_PK_FEATURE_UNAVAILABLE ); #endif } /* General case: no options */ if( options != NULL ) return( POLARSSL_ERR_PK_BAD_INPUT_DATA ); return( pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); }
/* get context to public key by parsing it */ pk_context getpubkeycontext(const unsigned char *rsapublickey, int rsapublickeylen){ pk_context pkctx = {0}; int pkresult = 0; pk_init(&pkctx); pkresult = pk_parse_public_key(&pkctx,rsapublickey,rsapublickeylen); if(pkresult != 0){ outputerror(DBG_ERROR,"%s\n","getpubkeycontext::failed to parse public key"); return pkctx; } pkresult = 0; pkresult = pk_can_do(&pkctx,POLARSSL_PK_RSA); if(pkresult != 1){ outputerror(DBG_ERROR,"%s\n","getpubkeycontext::key does not support RSA operations"); return pkctx; } return pkctx; }
static CURLcode polarssl_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; const char *capath = SSL_CONN_CONFIG(CApath); const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; int ret = -1; char errorbuf[128]; errorbuf[0]=0; /* PolarSSL only supports SSLv3 and TLSv1 */ if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "PolarSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func_mutex, &entropy, NULL, 0)) != 0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else entropy_init(&BACKEND->entropy); if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func, &BACKEND->entropy, NULL, 0)) != 0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ memset(&BACKEND->cacert, 0, sizeof(x509_crt)); if(SSL_CONN_CONFIG(CAfile)) { ret = x509_crt_parse_file(&BACKEND->cacert, SSL_CONN_CONFIG(CAfile)); if(ret<0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", SSL_CONN_CONFIG(CAfile), -ret, errorbuf); if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } } if(capath) { ret = x509_crt_parse_path(&BACKEND->cacert, capath); if(ret<0) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", capath, -ret, errorbuf); if(SSL_CONN_CONFIG(verifypeer)) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ memset(&BACKEND->clicert, 0, sizeof(x509_crt)); if(SSL_SET_OPTION(cert)) { ret = x509_crt_parse_file(&BACKEND->clicert, SSL_SET_OPTION(cert)); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", SSL_SET_OPTION(cert), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ if(SSL_SET_OPTION(key)) { pk_context pk; pk_init(&pk); ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key), SSL_SET_OPTION(key_passwd)); if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) ret = POLARSSL_ERR_PK_TYPE_MISMATCH; if(ret == 0) rsa_copy(&BACKEND->rsa, pk_rsa(pk)); else rsa_free(&BACKEND->rsa); pk_free(&pk); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", SSL_SET_OPTION(key), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ memset(&BACKEND->crl, 0, sizeof(x509_crl)); if(SSL_SET_OPTION(CRLfile)) { ret = x509_crl_parse_file(&BACKEND->crl, SSL_SET_OPTION(CRLfile)); if(ret) { error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", SSL_SET_OPTION(CRLfile), -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port); if(ssl_init(&BACKEND->ssl)) { failf(data, "PolarSSL: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); break; case CURL_SSLVERSION_SSLv3: ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: { CURLcode result = set_ssl_version_min_max(conn, sockindex); if(result != CURLE_OK) return result; break; } default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT); ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL); ssl_set_rng(&BACKEND->ssl, ctr_drbg_random, &BACKEND->ctr_drbg); ssl_set_bio(&BACKEND->ssl, net_recv, &conn->sock[sockindex], net_send, &conn->sock[sockindex]); ssl_set_ciphersuites(&BACKEND->ssl, ssl_list_ciphersuites()); /* Check if there's a cached ID we can/should use here! */ if(SSL_SET_OPTION(primary.sessionid)) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { ret = ssl_set_session(&BACKEND->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(conn); failf(data, "ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } infof(data, "PolarSSL re-using session\n"); } Curl_ssl_sessionid_unlock(conn); } ssl_set_ca_chain(&BACKEND->ssl, &BACKEND->cacert, &BACKEND->crl, hostname); ssl_set_own_cert_rsa(&BACKEND->ssl, &BACKEND->clicert, &BACKEND->rsa); if(ssl_set_hostname(&BACKEND->ssl, hostname)) { /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ failf(data, "couldn't set hostname in PolarSSL"); return CURLE_SSL_CONNECT_ERROR; } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { static const char *protocols[3]; int cur = 0; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } #endif protocols[cur++] = ALPN_HTTP_1_1; infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); protocols[cur] = NULL; ssl_set_alpn_protocols(&BACKEND->ssl, protocols); } #endif #ifdef POLARSSL_DEBUG ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; unsigned char tmp_buf[2048]; size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; pk_type_t pk_alg; /* * Prepare data to be signed in tmp_buf */ c = tmp_buf + sizeof( tmp_buf ); ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); if( len ) { ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) ); ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ, OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); } ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ); ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key, tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; /* * Subject ::= Name */ ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Prepare signature */ md( md_info_from_type( ctx->md_alg ), c, len, hash ); if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 ) { return( ret ); } if( pk_can_do( ctx->key, POLARSSL_PK_RSA ) ) pk_alg = POLARSSL_PK_RSA; else if( pk_can_do( ctx->key, POLARSSL_PK_ECDSA ) ) pk_alg = POLARSSL_PK_ECDSA; else return( POLARSSL_ERR_X509_INVALID_ALG ); if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); } /* * Write data to output buffer */ c2 = buf + size; ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, sig, sig_len ) ); if( len > (size_t)( c2 - buf ) ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); c2 -= len; memcpy( c2, c, len ); len += sig_and_oid_len; ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); return( (int) len ); }
int main( int argc, char *argv[] ) { FILE *f; int ret; pk_context pk; entropy_context entropy; ctr_drbg_context ctr_drbg; unsigned char hash[20]; unsigned char buf[POLARSSL_MPI_MAX_SIZE]; char filename[512]; const char *pers = "rsa_sign_pss"; size_t olen = 0; ret = 1; if( argc != 3 ) { printf( "usage: rsa_sign_pss <key_file> <filename>\n" ); #if defined(_WIN32) printf( "\n" ); #endif goto exit; } printf( "\n . Seeding the random number generator..." ); fflush( stdout ); entropy_init( &entropy ); if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { printf( " failed\n ! ctr_drbg_init returned %d\n", ret ); goto exit; } printf( "\n . Reading private key from '%s'", argv[1] ); fflush( stdout ); pk_init( &pk ); if( ( ret = pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 ) { ret = 1; printf( " failed\n ! Could not open '%s'\n", argv[1] ); goto exit; } if( !pk_can_do( &pk, POLARSSL_PK_RSA ) ) { ret = 1; printf( " failed\n ! Key is not an RSA key\n" ); goto exit; } /* * Compute the SHA-1 hash of the input file, * then calculate the RSA signature of the hash. */ printf( "\n . Generating the RSA/SHA-1 signature" ); fflush( stdout ); if( ( ret = sha1_file( argv[2], hash ) ) != 0 ) { printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); goto exit; } if( ( ret = pk_sign( &pk, POLARSSL_MD_SHA1, hash, 0, buf, &olen, ctr_drbg_random, &ctr_drbg ) ) != 0 ) { printf( " failed\n ! pk_sign returned %d\n\n", ret ); goto exit; } /* * Write the signature into <filename>-sig.txt */ snprintf( filename, 512, "%s.sig", argv[2] ); if( ( f = fopen( filename, "wb+" ) ) == NULL ) { ret = 1; printf( " failed\n ! Could not create %s\n\n", filename ); goto exit; } if( fwrite( buf, 1, olen, f ) != olen ) { printf( "failed\n ! fwrite failed\n\n" ); goto exit; } fclose( f ); printf( "\n . Done (created \"%s\")\n\n", filename ); exit: pk_free( &pk ); entropy_free( &entropy ); #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
static CURLcode polarssl_connect_step1(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; bool sni = TRUE; /* default is SNI enabled */ int ret = -1; #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif void *old_session = NULL; size_t old_session_size = 0; char errorbuf[128]; errorbuf[0]=0; /* PolarSSL only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "PolarSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy, connssl->ssn.id, connssl->ssn.length)) != 0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else entropy_init(&connssl->entropy); if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy, connssl->ssn.id, connssl->ssn.length)) != 0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ memset(&connssl->cacert, 0, sizeof(x509_crt)); if(data->set.str[STRING_SSL_CAFILE]) { ret = x509_crt_parse_file(&connssl->cacert, data->set.str[STRING_SSL_CAFILE]); if(ret<0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } if(data->set.str[STRING_SSL_CAPATH]) { ret = x509_crt_parse_path(&connssl->cacert, data->set.str[STRING_SSL_CAPATH]); if(ret<0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ memset(&connssl->clicert, 0, sizeof(x509_crt)); if(data->set.str[STRING_CERT]) { ret = x509_crt_parse_file(&connssl->clicert, data->set.str[STRING_CERT]); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_CERT], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ if(data->set.str[STRING_KEY]) { pk_context pk; pk_init(&pk); ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY], data->set.str[STRING_KEY_PASSWD]); if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) ret = POLARSSL_ERR_PK_TYPE_MISMATCH; if(ret == 0) rsa_copy(&connssl->rsa, pk_rsa(pk)); else rsa_free(&connssl->rsa); pk_free(&pk); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_KEY], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ memset(&connssl->crl, 0, sizeof(x509_crl)); if(data->set.str[STRING_SSL_CRLFILE]) { ret = x509_crl_parse_file(&connssl->crl, data->set.str[STRING_SSL_CRLFILE]); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "PolarSSL: Connecting to %s:%d\n", conn->host.name, conn->remote_port); if(ssl_init(&connssl->ssl)) { failf(data, "PolarSSL: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } switch(data->set.ssl.version) { default: case CURL_SSLVERSION_DEFAULT: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); break; case CURL_SSLVERSION_SSLv3: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n"); break; case CURL_SSLVERSION_TLSv1_1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n"); break; case CURL_SSLVERSION_TLSv1_2: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n"); break; } ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL); ssl_set_rng(&connssl->ssl, ctr_drbg_random, &connssl->ctr_drbg); ssl_set_bio(&connssl->ssl, net_recv, &conn->sock[sockindex], net_send, &conn->sock[sockindex]); ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites()); if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { memcpy(&connssl->ssn, old_session, old_session_size); infof(data, "PolarSSL re-using session\n"); } ssl_set_session(&connssl->ssl, &connssl->ssn); ssl_set_ca_chain(&connssl->ssl, &connssl->cacert, &connssl->crl, conn->host.name); ssl_set_own_cert_rsa(&connssl->ssl, &connssl->clicert, &connssl->rsa); if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) && #ifdef ENABLE_IPV6 !Curl_inet_pton(AF_INET6, conn->host.name, &addr) && #endif sni && ssl_set_hostname(&connssl->ssl, conn->host.name)) { infof(data, "WARNING: failed to configure " "server name indication (SNI) TLS extension\n"); } #ifdef HAS_ALPN if(data->set.httpversion == CURL_HTTP_VERSION_2_0) { if(data->set.ssl_enable_alpn) { static const char* protocols[] = { NGHTTP2_PROTO_VERSION_ID, ALPN_HTTP_1_1, NULL }; ssl_set_alpn_protocols(&connssl->ssl, protocols); infof(data, "ALPN, offering %s, %s\n", protocols[0], protocols[1]); } } #endif #ifdef POLARSSL_DEBUG ssl_set_dbg(&connssl->ssl, polarssl_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
static int x509_crt_verify_child( x509_crt *child, x509_crt *parent, x509_crt *trust_ca, x509_crl *ca_crl, int path_cnt, int *flags, int (*f_vrfy)(void *, x509_crt *, int, int *), void *p_vrfy ) { int ret; int parent_flags = 0; unsigned char hash[POLARSSL_MD_MAX_SIZE]; x509_crt *grandparent; const md_info_t *md_info; if( x509_time_expired( &child->valid_to ) ) *flags |= BADCERT_EXPIRED; md_info = md_info_from_type( child->sig_md ); if( md_info == NULL ) { /* * Cannot check 'unknown' hash */ *flags |= BADCERT_NOT_TRUSTED; } else { md( md_info, child->tbs.p, child->tbs.len, hash ); if( pk_can_do( &parent->pk, child->sig_pk ) == 0 || pk_verify( &parent->pk, child->sig_md, hash, md_info->size, child->sig.p, child->sig.len ) != 0 ) { *flags |= BADCERT_NOT_TRUSTED; } } #if defined(POLARSSL_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the given crt */ *flags |= x509_crt_verifycrl(child, parent, ca_crl); #endif grandparent = parent->next; while( grandparent != NULL ) { if( grandparent->version == 0 || grandparent->ca_istrue == 0 || parent->issuer_raw.len != grandparent->subject_raw.len || memcmp( parent->issuer_raw.p, grandparent->subject_raw.p, parent->issuer_raw.len ) != 0 ) { grandparent = grandparent->next; continue; } break; } if( grandparent != NULL ) { /* * Part of the chain */ ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } else { ret = x509_crt_verify_top( parent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy ); if( ret != 0 ) return( ret ); } /* child is verified to be a child of the parent, call verify callback */ if( NULL != f_vrfy ) if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) return( ret ); *flags |= parent_flags; return( 0 ); }
int main( int argc, char *argv[] ) { int ret, i; x509_crt cacert; x509_crl crl; char buf[10240]; ((void) argc); ((void) argv); x509_crt_init( &cacert ); x509_crl_init( &crl ); /* * 1.1. Load the trusted CA */ printf( "\n . Loading the CA root certificate ..." ); fflush( stdout ); /* * Alternatively, you may load the CA certificates from a .pem or * .crt file by calling x509_crt_parse_file( &cacert, "myca.crt" ). */ ret = x509_crt_parse_file( &cacert, "ssl/test-ca/test-ca.crt" ); if( ret != 0 ) { printf( " failed\n ! x509_crt_parse_file returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); x509_crt_info( buf, 1024, "CRT: ", &cacert ); printf("%s\n", buf ); /* * 1.2. Load the CRL */ printf( " . Loading the CRL ..." ); fflush( stdout ); ret = x509_crl_parse_file( &crl, "ssl/test-ca/crl.pem" ); if( ret != 0 ) { printf( " failed\n ! x509_crl_parse_file returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); x509_crl_info( buf, 1024, "CRL: ", &crl ); printf("%s\n", buf ); for( i = 0; i < MAX_CLIENT_CERTS; i++ ) { /* * 1.3. Load own certificate */ char name[512]; int flags; x509_crt clicert; pk_context pk; x509_crt_init( &clicert ); pk_init( &pk ); snprintf(name, 512, "ssl/test-ca/%s", client_certificates[i]); printf( " . Loading the client certificate %s...", name ); fflush( stdout ); ret = x509_crt_parse_file( &clicert, name ); if( ret != 0 ) { printf( " failed\n ! x509_crt_parse_file returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); /* * 1.4. Verify certificate validity with CA certificate */ printf( " . Verify the client certificate with CA certificate..." ); fflush( stdout ); ret = x509_crt_verify( &clicert, &cacert, &crl, NULL, &flags, NULL, NULL ); if( ret != 0 ) { if( ret == POLARSSL_ERR_X509_CERT_VERIFY_FAILED ) { if( flags & BADCERT_CN_MISMATCH ) printf( " CN_MISMATCH " ); if( flags & BADCERT_EXPIRED ) printf( " EXPIRED " ); if( flags & BADCERT_REVOKED ) printf( " REVOKED " ); if( flags & BADCERT_NOT_TRUSTED ) printf( " NOT_TRUSTED " ); if( flags & BADCRL_NOT_TRUSTED ) printf( " CRL_NOT_TRUSTED " ); if( flags & BADCRL_EXPIRED ) printf( " CRL_EXPIRED " ); } else { printf( " failed\n ! x509_crt_verify returned %d\n\n", ret ); goto exit; } } printf( " ok\n" ); /* * 1.5. Load own private key */ snprintf(name, 512, "ssl/test-ca/%s", client_private_keys[i]); printf( " . Loading the client private key %s...", name ); fflush( stdout ); ret = pk_parse_keyfile( &pk, name, NULL ); if( ret != 0 ) { printf( " failed\n ! pk_parse_keyfile returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); /* * 1.6. Verify certificate validity with private key */ printf( " . Verify the client certificate with private key..." ); fflush( stdout ); /* EC NOT IMPLEMENTED YET */ if( ! pk_can_do( &clicert.pk, POLARSSL_PK_RSA ) ) { printf( " failed\n ! certificate's key is not RSA\n\n" ); ret = POLARSSL_ERR_X509_FEATURE_UNAVAILABLE; goto exit; } ret = mpi_cmp_mpi(&pk_rsa( pk )->N, &pk_rsa( clicert.pk )->N); if( ret != 0 ) { printf( " failed\n ! mpi_cmp_mpi for N returned %d\n\n", ret ); goto exit; } ret = mpi_cmp_mpi(&pk_rsa( pk )->E, &pk_rsa( clicert.pk )->E); if( ret != 0 ) { printf( " failed\n ! mpi_cmp_mpi for E returned %d\n\n", ret ); goto exit; } ret = rsa_check_privkey( pk_rsa( pk ) ); if( ret != 0 ) { printf( " failed\n ! rsa_check_privkey returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); x509_crt_free( &clicert ); pk_free( &pk ); } exit: x509_crt_free( &cacert ); x509_crl_free( &crl ); #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
static int x509_crt_verify_top( x509_crt *child, x509_crt *trust_ca, x509_crl *ca_crl, int path_cnt, int *flags, int (*f_vrfy)(void *, x509_crt *, int, int *), void *p_vrfy ) { int ret; int ca_flags = 0, check_path_cnt = path_cnt + 1; unsigned char hash[POLARSSL_MD_MAX_SIZE]; const md_info_t *md_info; if( x509_time_expired( &child->valid_to ) ) *flags |= BADCERT_EXPIRED; /* * Child is the top of the chain. Check against the trust_ca list. */ *flags |= BADCERT_NOT_TRUSTED; md_info = md_info_from_type( child->sig_md ); if( md_info == NULL ) { /* * Cannot check 'unknown', no need to try any CA */ trust_ca = NULL; } else md( md_info, child->tbs.p, child->tbs.len, hash ); while( trust_ca != NULL ) { if( trust_ca->version == 0 || child->issuer_raw.len != trust_ca->subject_raw.len || memcmp( child->issuer_raw.p, trust_ca->subject_raw.p, child->issuer_raw.len ) != 0 ) { trust_ca = trust_ca->next; continue; } /* * Reduce path_len to check against if top of the chain is * the same as the trusted CA */ if( child->subject_raw.len == trust_ca->subject_raw.len && memcmp( child->subject_raw.p, trust_ca->subject_raw.p, child->issuer_raw.len ) == 0 ) { check_path_cnt--; } if( trust_ca->max_pathlen > 0 && trust_ca->max_pathlen < check_path_cnt ) { trust_ca = trust_ca->next; continue; } if( pk_can_do( &trust_ca->pk, child->sig_pk ) == 0 || pk_verify( &trust_ca->pk, child->sig_md, hash, md_info->size, child->sig.p, child->sig.len ) != 0 ) { trust_ca = trust_ca->next; continue; } /* * Top of chain is signed by a trusted CA */ *flags &= ~BADCERT_NOT_TRUSTED; break; } /* * If top of chain is not the same as the trusted CA send a verify request * to the callback for any issues with validity and CRL presence for the * trusted CA certificate. */ if( trust_ca != NULL && ( child->subject_raw.len != trust_ca->subject_raw.len || memcmp( child->subject_raw.p, trust_ca->subject_raw.p, child->issuer_raw.len ) != 0 ) ) { #if defined(POLARSSL_X509_CRL_PARSE_C) /* Check trusted CA's CRL for the chain's top crt */ *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl ); #else ((void) ca_crl); #endif if( x509_time_expired( &trust_ca->valid_to ) ) ca_flags |= BADCERT_EXPIRED; if( NULL != f_vrfy ) { if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, &ca_flags ) ) != 0 ) return( ret ); } } /* Call callback on top cert */ if( NULL != f_vrfy ) { if( ( ret = f_vrfy(p_vrfy, child, path_cnt, flags ) ) != 0 ) return( ret ); } *flags |= ca_flags; return( 0 ); }
/* * Check that the given certificate is valid according to the CRL. */ static int x509_crt_verifycrl( x509_crt *crt, x509_crt *ca, x509_crl *crl_list) { int flags = 0; unsigned char hash[POLARSSL_MD_MAX_SIZE]; const md_info_t *md_info; if( ca == NULL ) return( flags ); /* * TODO: What happens if no CRL is present? * Suggestion: Revocation state should be unknown if no CRL is present. * For backwards compatibility this is not yet implemented. */ while( crl_list != NULL ) { if( crl_list->version == 0 || crl_list->issuer_raw.len != ca->subject_raw.len || memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, crl_list->issuer_raw.len ) != 0 ) { crl_list = crl_list->next; continue; } /* * Check if CRL is correctly signed by the trusted CA */ md_info = md_info_from_type( crl_list->sig_md ); if( md_info == NULL ) { /* * Cannot check 'unknown' hash */ flags |= BADCRL_NOT_TRUSTED; break; } md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); if( pk_can_do( &ca->pk, crl_list->sig_pk ) == 0 || pk_verify( &ca->pk, crl_list->sig_md, hash, md_info->size, crl_list->sig.p, crl_list->sig.len ) != 0 ) { flags |= BADCRL_NOT_TRUSTED; break; } /* * Check for validity of CRL (Do not drop out) */ if( x509_time_expired( &crl_list->next_update ) ) flags |= BADCRL_EXPIRED; /* * Check if certificate is revoked */ if( x509_crt_revoked(crt, crl_list) ) { flags |= BADCERT_REVOKED; break; } crl_list = crl_list->next; } return flags; }
static CURLcode polarssl_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; bool sni = TRUE; /* default is SNI enabled */ int ret = -1; #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif char errorbuf[128]; errorbuf[0]=0; /* PolarSSL only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "PolarSSL does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func_mutex, &entropy, NULL, 0)) != 0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else entropy_init(&connssl->entropy); if((ret = ctr_drbg_init(&connssl->ctr_drbg, entropy_func, &connssl->entropy, NULL, 0)) != 0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ memset(&connssl->cacert, 0, sizeof(x509_crt)); if(data->set.str[STRING_SSL_CAFILE]) { ret = x509_crt_parse_file(&connssl->cacert, data->set.str[STRING_SSL_CAFILE]); if(ret<0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } if(data->set.str[STRING_SSL_CAPATH]) { ret = x509_crt_parse_path(&connssl->cacert, data->set.str[STRING_SSL_CAPATH]); if(ret<0) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ memset(&connssl->clicert, 0, sizeof(x509_crt)); if(data->set.str[STRING_CERT]) { ret = x509_crt_parse_file(&connssl->clicert, data->set.str[STRING_CERT]); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_CERT], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ if(data->set.str[STRING_KEY]) { pk_context pk; pk_init(&pk); ret = pk_parse_keyfile(&pk, data->set.str[STRING_KEY], data->set.str[STRING_KEY_PASSWD]); if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA)) ret = POLARSSL_ERR_PK_TYPE_MISMATCH; if(ret == 0) rsa_copy(&connssl->rsa, pk_rsa(pk)); else rsa_free(&connssl->rsa); pk_free(&pk); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_KEY], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ memset(&connssl->crl, 0, sizeof(x509_crl)); if(data->set.str[STRING_SSL_CRLFILE]) { ret = x509_crl_parse_file(&connssl->crl, data->set.str[STRING_SSL_CRLFILE]); if(ret) { #ifdef POLARSSL_ERROR_C error_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* POLARSSL_ERROR_C */ failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s", data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "PolarSSL: Connecting to %s:%d\n", conn->host.name, conn->remote_port); if(ssl_init(&connssl->ssl)) { failf(data, "PolarSSL: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } switch(data->set.ssl.version) { default: case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); break; case CURL_SSLVERSION_SSLv3: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_0); infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.0\n"); break; case CURL_SSLVERSION_TLSv1_1: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2); ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_2); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.1\n"); break; case CURL_SSLVERSION_TLSv1_2: ssl_set_min_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3); ssl_set_max_version(&connssl->ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_3); infof(data, "PolarSSL: Forced min. SSL Version to be TLS 1.2\n"); break; } ssl_set_endpoint(&connssl->ssl, SSL_IS_CLIENT); ssl_set_authmode(&connssl->ssl, SSL_VERIFY_OPTIONAL); ssl_set_rng(&connssl->ssl, ctr_drbg_random, &connssl->ctr_drbg); ssl_set_bio(&connssl->ssl, net_recv, &conn->sock[sockindex], net_send, &conn->sock[sockindex]); ssl_set_ciphersuites(&connssl->ssl, ssl_list_ciphersuites()); /* Check if there's a cached ID we can/should use here! */ if(conn->ssl_config.sessionid) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) { ret = ssl_set_session(&connssl->ssl, old_session); Curl_ssl_sessionid_unlock(conn); if(ret) { failf(data, "ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } infof(data, "PolarSSL re-using session\n"); } } ssl_set_ca_chain(&connssl->ssl, &connssl->cacert, &connssl->crl, conn->host.name); ssl_set_own_cert_rsa(&connssl->ssl, &connssl->clicert, &connssl->rsa); if(ssl_set_hostname(&connssl->ssl, conn->host.name)) { /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ failf(data, "couldn't set hostname in PolarSSL"); return CURLE_SSL_CONNECT_ERROR; } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { static const char* protocols[3]; int cur = 0; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) { protocols[cur++] = NGHTTP2_PROTO_VERSION_ID; infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID); } #endif protocols[cur++] = ALPN_HTTP_1_1; infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); protocols[cur] = NULL; ssl_set_alpn_protocols(&connssl->ssl, protocols); } #endif #ifdef POLARSSL_DEBUG ssl_set_dbg(&connssl->ssl, polarssl_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
int main( int argc, char *argv[] ) { int ret = 0; x509_crt issuer_crt; pk_context loaded_issuer_key, loaded_subject_key; pk_context *issuer_key = &loaded_issuer_key, *subject_key = &loaded_subject_key; char buf[1024]; char issuer_name[128]; int i, j, n; char *p, *q, *r; #if defined(POLARSSL_X509_CSR_PARSE_C) char subject_name[128]; x509_csr csr; #endif x509write_cert crt; mpi serial; entropy_context entropy; ctr_drbg_context ctr_drbg; const char *pers = "crt example app"; /* * Set to sane values */ x509write_crt_init( &crt ); x509write_crt_set_md_alg( &crt, POLARSSL_MD_SHA1 ); pk_init( &loaded_issuer_key ); pk_init( &loaded_subject_key ); mpi_init( &serial ); #if defined(POLARSSL_X509_CSR_PARSE_C) x509_csr_init( &csr ); #endif x509_crt_init( &issuer_crt ); memset( buf, 0, 1024 ); if( argc == 0 ) { usage: printf( USAGE ); ret = 1; goto exit; } opt.issuer_crt = DFL_ISSUER_CRT; opt.request_file = DFL_REQUEST_FILE; opt.request_file = DFL_REQUEST_FILE; opt.subject_key = DFL_SUBJECT_KEY; opt.issuer_key = DFL_ISSUER_KEY; opt.subject_pwd = DFL_SUBJECT_PWD; opt.issuer_pwd = DFL_ISSUER_PWD; opt.output_file = DFL_OUTPUT_FILENAME; opt.subject_name = DFL_SUBJECT_NAME; opt.issuer_name = DFL_ISSUER_NAME; opt.not_before = DFL_NOT_BEFORE; opt.not_after = DFL_NOT_AFTER; opt.serial = DFL_SERIAL; opt.selfsign = DFL_SELFSIGN; opt.is_ca = DFL_IS_CA; opt.max_pathlen = DFL_MAX_PATHLEN; opt.key_usage = DFL_KEY_USAGE; opt.ns_cert_type = DFL_NS_CERT_TYPE; for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; n = strlen( p ); for( j = 0; j < n; j++ ) { if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' ) argv[i][j] |= 0x20; } if( strcmp( p, "request_file" ) == 0 ) opt.request_file = q; else if( strcmp( p, "subject_key" ) == 0 ) opt.subject_key = q; else if( strcmp( p, "issuer_key" ) == 0 ) opt.issuer_key = q; else if( strcmp( p, "subject_pwd" ) == 0 ) opt.subject_pwd = q; else if( strcmp( p, "issuer_pwd" ) == 0 ) opt.issuer_pwd = q; else if( strcmp( p, "issuer_crt" ) == 0 ) opt.issuer_crt = q; else if( strcmp( p, "output_file" ) == 0 ) opt.output_file = q; else if( strcmp( p, "subject_name" ) == 0 ) { opt.subject_name = q; } else if( strcmp( p, "issuer_name" ) == 0 ) { opt.issuer_name = q; } else if( strcmp( p, "not_before" ) == 0 ) { opt.not_before = q; } else if( strcmp( p, "not_after" ) == 0 ) { opt.not_after = q; } else if( strcmp( p, "serial" ) == 0 ) { opt.serial = q; } else if( strcmp( p, "selfsign" ) == 0 ) { opt.selfsign = atoi( q ); if( opt.selfsign < 0 || opt.selfsign > 1 ) goto usage; } else if( strcmp( p, "is_ca" ) == 0 ) { opt.is_ca = atoi( q ); if( opt.is_ca < 0 || opt.is_ca > 1 ) goto usage; } else if( strcmp( p, "max_pathlen" ) == 0 ) { opt.max_pathlen = atoi( q ); if( opt.max_pathlen < -1 || opt.max_pathlen > 127 ) goto usage; } else if( strcmp( p, "key_usage" ) == 0 ) { while( q != NULL ) { if( ( r = strchr( q, ',' ) ) != NULL ) *r++ = '\0'; if( strcmp( q, "digital_signature" ) == 0 ) opt.key_usage |= KU_DIGITAL_SIGNATURE; else if( strcmp( q, "non_repudiation" ) == 0 ) opt.key_usage |= KU_NON_REPUDIATION; else if( strcmp( q, "key_encipherment" ) == 0 ) opt.key_usage |= KU_KEY_ENCIPHERMENT; else if( strcmp( q, "data_encipherment" ) == 0 ) opt.key_usage |= KU_DATA_ENCIPHERMENT; else if( strcmp( q, "key_agreement" ) == 0 ) opt.key_usage |= KU_KEY_AGREEMENT; else if( strcmp( q, "key_cert_sign" ) == 0 ) opt.key_usage |= KU_KEY_CERT_SIGN; else if( strcmp( q, "crl_sign" ) == 0 ) opt.key_usage |= KU_CRL_SIGN; else goto usage; q = r; } } else if( strcmp( p, "ns_cert_type" ) == 0 ) { while( q != NULL ) { if( ( r = strchr( q, ',' ) ) != NULL ) *r++ = '\0'; if( strcmp( q, "ssl_client" ) == 0 ) opt.ns_cert_type |= NS_CERT_TYPE_SSL_CLIENT; else if( strcmp( q, "ssl_server" ) == 0 ) opt.ns_cert_type |= NS_CERT_TYPE_SSL_SERVER; else if( strcmp( q, "email" ) == 0 ) opt.ns_cert_type |= NS_CERT_TYPE_EMAIL; else if( strcmp( q, "object_signing" ) == 0 ) opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING; else if( strcmp( q, "ssl_ca" ) == 0 ) opt.ns_cert_type |= NS_CERT_TYPE_SSL_CA; else if( strcmp( q, "email_ca" ) == 0 ) opt.ns_cert_type |= NS_CERT_TYPE_EMAIL_CA; else if( strcmp( q, "object_signing_ca" ) == 0 ) opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING_CA; else goto usage; q = r; } } else goto usage; } printf("\n"); /* * 0. Seed the PRNG */ printf( " . Seeding the random number generator..." ); fflush( stdout ); entropy_init( &entropy ); if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! ctr_drbg_init returned %d - %s\n", ret, buf ); goto exit; } printf( " ok\n" ); // Parse serial to MPI // printf( " . Reading serial number..." ); fflush( stdout ); if( ( ret = mpi_read_string( &serial, 10, opt.serial ) ) != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! mpi_read_string returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); // Parse issuer certificate if present // if( !opt.selfsign && strlen( opt.issuer_crt ) ) { /* * 1.0.a. Load the certificates */ printf( " . Loading the issuer certificate ..." ); fflush( stdout ); if( ( ret = x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509_crt_parse_file returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } ret = x509_dn_gets( issuer_name, sizeof(issuer_name), &issuer_crt.issuer ); if( ret < 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } opt.issuer_name = issuer_name; printf( " ok\n" ); } #if defined(POLARSSL_X509_CSR_PARSE_C) // Parse certificate request if present // if( !opt.selfsign && strlen( opt.request_file ) ) { /* * 1.0.b. Load the CSR */ printf( " . Loading the certificate request ..." ); fflush( stdout ); if( ( ret = x509_csr_parse_file( &csr, opt.request_file ) ) != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509_csr_parse_file returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } ret = x509_dn_gets( subject_name, sizeof(subject_name), &csr.subject ); if( ret < 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } opt.subject_name = subject_name; subject_key = &csr.pk; printf( " ok\n" ); } #endif /* POLARSSL_X509_CSR_PARSE_C */ /* * 1.1. Load the keys */ if( !opt.selfsign && !strlen( opt.request_file ) ) { printf( " . Loading the subject key ..." ); fflush( stdout ); ret = pk_parse_keyfile( &loaded_subject_key, opt.subject_key, opt.subject_pwd ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! pk_parse_keyfile returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); } printf( " . Loading the issuer key ..." ); fflush( stdout ); ret = pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key, opt.issuer_pwd ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! pk_parse_keyfile returned -x%02x - %s\n\n", -ret, buf ); goto exit; } // Check if key and issuer certificate match // if( strlen( opt.issuer_crt ) ) { if( !pk_can_do( &issuer_crt.pk, POLARSSL_PK_RSA ) || mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->N, &pk_rsa( *issuer_key )->N ) != 0 || mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->E, &pk_rsa( *issuer_key )->E ) != 0 ) { printf( " failed\n ! issuer_key does not match issuer certificate\n\n" ); ret = -1; goto exit; } } printf( " ok\n" ); if( opt.selfsign ) { opt.subject_name = opt.issuer_name; subject_key = issuer_key; } x509write_crt_set_subject_key( &crt, subject_key ); x509write_crt_set_issuer_key( &crt, issuer_key ); /* * 1.0. Check the names for validity */ if( ( ret = x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509write_crt_set_subject_name returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } if( ( ret = x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509write_crt_set_issuer_name returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " . Setting certificate values ..." ); fflush( stdout ); ret = x509write_crt_set_serial( &crt, &serial ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509write_crt_set_serial returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } ret = x509write_crt_set_validity( &crt, opt.not_before, opt.not_after ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509write_crt_set_validity returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); printf( " . Adding the Basic Constraints extension ..." ); fflush( stdout ); ret = x509write_crt_set_basic_constraints( &crt, opt.is_ca, opt.max_pathlen ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509write_crt_set_basic_contraints returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); #if defined(POLARSSL_SHA1_C) printf( " . Adding the Subject Key Identifier ..." ); fflush( stdout ); ret = x509write_crt_set_subject_key_identifier( &crt ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509write_crt_set_subject_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); printf( " . Adding the Authority Key Identifier ..." ); fflush( stdout ); ret = x509write_crt_set_authority_key_identifier( &crt ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509write_crt_set_authority_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); #endif /* POLARSSL_SHA1_C */ if( opt.key_usage ) { printf( " . Adding the Key Usage extension ..." ); fflush( stdout ); ret = x509write_crt_set_key_usage( &crt, opt.key_usage ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509write_crt_set_key_usage returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); } if( opt.ns_cert_type ) { printf( " . Adding the NS Cert Type extension ..." ); fflush( stdout ); ret = x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type ); if( ret != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! x509write_crt_set_ns_cert_type returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); } /* * 1.2. Writing the request */ printf( " . Writing the certificate..." ); fflush( stdout ); if( ( ret = write_certificate( &crt, opt.output_file, ctr_drbg_random, &ctr_drbg ) ) != 0 ) { error_strerror( ret, buf, 1024 ); printf( " failed\n ! write_certifcate -0x%02x - %s\n\n", -ret, buf ); goto exit; } printf( " ok\n" ); exit: x509write_crt_free( &crt ); pk_free( &loaded_subject_key ); pk_free( &loaded_issuer_key ); mpi_free( &serial ); entropy_free( &entropy ); #if defined(_WIN32) printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
belle_sip_signing_key_t* belle_sip_signing_key_parse(const char* buff, size_t size,const char* passwd) { #ifdef HAVE_POLARSSL belle_sip_signing_key_t* signing_key = belle_sip_object_new(belle_sip_signing_key_t); int err; #if POLARSSL_VERSION_NUMBER < 0x01030000 if ((err=x509parse_key(&signing_key->key,(const unsigned char *)buff,size,(const unsigned char*)passwd,passwd?strlen(passwd):0)) <0) { #else pk_init(&signing_key->key); /* for API v1.3 or greater also parses public keys other than RSA */ err=pk_parse_key(&signing_key->key,(const unsigned char *)buff,size,(const unsigned char*)passwd,passwd?strlen(passwd):0); /* make sure cipher is RSA to be consistent with API v1.2 */ if(err==0 && !pk_can_do(&signing_key->key,POLARSSL_PK_RSA)) err=POLARSSL_ERR_PK_TYPE_MISMATCH; if (err<0) { #endif char tmp[128]; error_strerror(err,tmp,sizeof(tmp)); belle_sip_error("cannot parse public key because [%s]",tmp); #if POLARSSL_VERSION_NUMBER >= 0x01030000 pk_free(&signing_key->key); #endif belle_sip_object_unref(signing_key); return NULL; } return signing_key; #else /*HAVE_POLARSSL*/ return NULL; #endif } belle_sip_signing_key_t* belle_sip_signing_key_parse_file(const char* path,const char* passwd) { #ifdef HAVE_POLARSSL belle_sip_signing_key_t* signing_key = belle_sip_object_new(belle_sip_signing_key_t); int err; #if POLARSSL_VERSION_NUMBER < 0x01030000 if ((err=x509parse_keyfile(&signing_key->key,path, passwd)) <0) { #else pk_init(&signing_key->key); /* for API v1.3 or greater also parses public keys other than RSA */ err=pk_parse_keyfile(&signing_key->key,path, passwd); /* make sure cipher is RSA to be consistent with API v1.2 */ if(err==0 && !pk_can_do(&signing_key->key,POLARSSL_PK_RSA)) err=POLARSSL_ERR_PK_TYPE_MISMATCH; if (err<0) { #endif char tmp[128]; error_strerror(err,tmp,sizeof(tmp)); belle_sip_error("cannot parse public key because [%s]",tmp); #if POLARSSL_VERSION_NUMBER >= 0x01030000 pk_free(&signing_key->key); #endif belle_sip_object_unref(signing_key); return NULL; } return signing_key; #else /*HAVE_POLARSSL*/ return NULL; #endif } static void belle_sip_signing_key_destroy(belle_sip_signing_key_t *signing_key){ #ifdef HAVE_POLARSSL #if POLARSSL_VERSION_NUMBER < 0x01030000 rsa_free(&signing_key->key); #else pk_free(&signing_key->key); #endif #endif }