/** * Block symmetric ciphers. * Please note that linker-override is possible, but dynamic override is generally * preferable to avoid clobbering all symmetric support. * * @param uint8_t* Buffer containing plaintext. * @param int Length of plaintext. * @param uint8_t* Target buffer for ciphertext. * @param int Length of output. * @param uint8_t* Buffer containing the symmetric key. * @param int Length of the key, in bits. * @param uint8_t* IV. Caller's responsibility to use correct size. * @param Cipher The cipher by which to encrypt. * @param uint32_t Options to the optionation. * @return true if the root function ought to defer. */ int __attribute__((weak)) wrapped_sym_cipher(uint8_t* in, int in_len, uint8_t* out, int out_len, uint8_t* key, int key_len, uint8_t* iv, Cipher ci, uint32_t opts) { if (cipher_deferred_handling(ci)) { // If overriden by user implementation. return _sym_overrides[ci](in, in_len, out, out_len, key, key_len, iv, ci, opts); } int8_t ret = -1; switch (ci) { #if defined(MBEDTLS_AES_C) case Cipher::SYM_AES_256_CBC: case Cipher::SYM_AES_192_CBC: case Cipher::SYM_AES_128_CBC: { mbedtls_aes_context ctx; if (opts & OP_ENCRYPT) { mbedtls_aes_setkey_enc(&ctx, key, (unsigned int) key_len); } else { mbedtls_aes_setkey_dec(&ctx, key, (unsigned int) key_len); } ret = mbedtls_aes_crypt_cbc(&ctx, _cipher_opcode(ci, opts), in_len, iv, in, out); mbedtls_aes_free(&ctx); } break; #endif #if defined(MBEDTLS_RSA_C) case Cipher::ASYM_RSA: { mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ctr_drbg_init(&ctr_drbg); size_t olen = 0; mbedtls_pk_context ctx; mbedtls_pk_init(&ctx); if (opts & OP_ENCRYPT) { ret = mbedtls_pk_encrypt(&ctx, in, in_len, out, &olen, out_len, mbedtls_ctr_drbg_random, &ctr_drbg); } else { ret = mbedtls_pk_decrypt(&ctx, in, in_len, out, &olen, out_len, mbedtls_ctr_drbg_random, &ctr_drbg); } mbedtls_pk_free(&ctx); } break; #endif #if defined(MBEDTLS_BLOWFISH_C) case Cipher::SYM_BLOWFISH_CBC: { mbedtls_blowfish_context ctx; mbedtls_blowfish_setkey(&ctx, key, key_len); ret = mbedtls_blowfish_crypt_cbc(&ctx, _cipher_opcode(ci, opts), in_len, iv, in, out); mbedtls_blowfish_free(&ctx); } break; #endif #if defined(WRAPPED_SYM_NULL) case Cipher::SYM_NULL: memcpy(out, in, in_len); ret = 0; break; #endif default: break; } return ret; }
mbedtls_x509_crt *load_cert_file( const char *ca_file, const char *certfile ) { int ret = 0; unsigned char buf[1024]; mbedtls_net_context server_fd; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; mbedtls_x509_crt *cur; mbedtls_x509_crt *cert; mbedtls_pk_context pkey; int i; uint32_t flags; int verify = 0; char *p, *q; /* * Set to sane values */ cert = (mbedtls_x509_crt *)mbedtls_calloc(1, sizeof(*cert)); cur = cert; mbedtls_x509_crt_init( cert ); mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_x509_crt_init( &cacert ); /* Zeroize structure as CRL parsing is not supported and we have to pass it to the verify function */ mbedtls_pk_init( &pkey ); /* * 1.1. Load the trusted CA */ mbedtls_printf( " . Loading the CA root certificate ..." ); fflush( stdout ); ret = mbedtls_x509_crt_parse_file( &cacert, ca_file ); if( ret < 0 ) { fprintf(stderr, " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); return NULL; } mbedtls_printf( " ok (%d skipped)\n", ret ); /* * 1.1. Load the certificate(s) */ printf( "\n . Loading the certificate at: %s ...", certfile); ret = mbedtls_x509_crt_parse_file( cert, certfile ); if( ret < 0 ) { char errorbuf[256]; mbedtls_strerror( ret, errorbuf, sizeof(errorbuf)); printf( " failed\n ! mbedtls_x509_crt_parse_file returned %d: %s\n\n", ret, errorbuf ); mbedtls_x509_crt_free( cert ); goto exit; } printf( " ok\n" ); /* * 1.2 Print the certificate(s) */ while( cur != NULL ) { printf( " . Peer certificate information ...\n" ); ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", cur ); if( ret == -1 ) { printf( " failed\n ! mbedtls_x509_crt_info returned %d\n\n", ret ); goto exit; } printf( "%s\n", buf ); cur = cur->next; } ret = 0; /* * 1.3 Verify the certificate */ printf( " . Verifying X.509 certificate..." ); if( ( ret = mbedtls_x509_crt_verify( cert, &cacert, NULL, NULL, &flags, my_verify, NULL ) ) != 0 ) { char vrfy_buf[512]; printf( " failed\n" ); mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); printf( "%s\n", vrfy_buf ); goto exit; } else printf( " ok\n" ); exit: //mbedtls_net_free( &server_fd ); mbedtls_x509_crt_free( &cacert ); mbedtls_pk_free( &pkey ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); if( ret < 0 ) { mbedtls_x509_crt_free( cert ); mbedtls_free(cert); return NULL; } return cert; }
int main( void ) { int ret, i; mbedtls_x509_crt cacert; mbedtls_x509_crl crl; char buf[10240]; mbedtls_x509_crt_init( &cacert ); mbedtls_x509_crl_init( &crl ); /* * 1.1. Load the trusted CA */ mbedtls_printf( "\n . Loading the CA root certificate ..." ); fflush( stdout ); /* * Alternatively, you may load the CA certificates from a .pem or * .crt file by calling mbedtls_x509_crt_parse_file( &cacert, "myca.crt" ). */ ret = mbedtls_x509_crt_parse_file( &cacert, "ssl/test-ca/test-ca.crt" ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); mbedtls_x509_crt_info( buf, 1024, "CRT: ", &cacert ); mbedtls_printf("%s\n", buf ); /* * 1.2. Load the CRL */ mbedtls_printf( " . Loading the CRL ..." ); fflush( stdout ); ret = mbedtls_x509_crl_parse_file( &crl, "ssl/test-ca/crl.pem" ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crl_parse_file returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); mbedtls_x509_crl_info( buf, 1024, "CRL: ", &crl ); mbedtls_printf("%s\n", buf ); for( i = 0; i < MAX_CLIENT_CERTS; i++ ) { /* * 1.3. Load own certificate */ char name[512]; uint32_t flags; mbedtls_x509_crt clicert; mbedtls_pk_context pk; mbedtls_x509_crt_init( &clicert ); mbedtls_pk_init( &pk ); mbedtls_snprintf(name, 512, "ssl/test-ca/%s", client_certificates[i]); mbedtls_printf( " . Loading the client certificate %s...", name ); fflush( stdout ); ret = mbedtls_x509_crt_parse_file( &clicert, name ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1.4. Verify certificate validity with CA certificate */ mbedtls_printf( " . Verify the client certificate with CA certificate..." ); fflush( stdout ); ret = mbedtls_x509_crt_verify( &clicert, &cacert, &crl, NULL, &flags, NULL, NULL ); if( ret != 0 ) { if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) { char vrfy_buf[512]; mbedtls_printf( " failed\n" ); mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); mbedtls_printf( "%s\n", vrfy_buf ); } else { mbedtls_printf( " failed\n ! mbedtls_x509_crt_verify returned %d\n\n", ret ); goto exit; } } mbedtls_printf( " ok\n" ); /* * 1.5. Load own private key */ mbedtls_snprintf(name, 512, "ssl/test-ca/%s", client_private_keys[i]); mbedtls_printf( " . Loading the client private key %s...", name ); fflush( stdout ); ret = mbedtls_pk_parse_keyfile( &pk, name, NULL ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1.6. Verify certificate validity with private key */ mbedtls_printf( " . Verify the client certificate with private key..." ); fflush( stdout ); /* EC NOT IMPLEMENTED YET */ if( ! mbedtls_pk_can_do( &clicert.pk, MBEDTLS_PK_RSA ) ) { mbedtls_printf( " failed\n ! certificate's key is not RSA\n\n" ); ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; goto exit; } ret = mbedtls_mpi_cmp_mpi(&mbedtls_pk_rsa( pk )->N, &mbedtls_pk_rsa( clicert.pk )->N); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_cmp_mpi for N returned %d\n\n", ret ); goto exit; } ret = mbedtls_mpi_cmp_mpi(&mbedtls_pk_rsa( pk )->E, &mbedtls_pk_rsa( clicert.pk )->E); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_cmp_mpi for E returned %d\n\n", ret ); goto exit; } ret = mbedtls_rsa_check_privkey( mbedtls_pk_rsa( pk ) ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_rsa_check_privkey returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); mbedtls_x509_crt_free( &clicert ); mbedtls_pk_free( &pk ); } exit: mbedtls_x509_crt_free( &cacert ); mbedtls_x509_crl_free( &crl ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( void ) { int ret, len; mbedtls_net_context listen_fd, client_fd; unsigned char buf[1024]; const char *pers = "dtls_server"; unsigned char client_ip[16] = { 0 }; size_t cliip_len; mbedtls_ssl_cookie_ctx cookie_ctx; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; mbedtls_timing_delay_context timer; #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); mbedtls_ssl_cookie_init( &cookie_ctx ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_pk_init( &pkey ); mbedtls_entropy_init( &entropy ); mbedtls_ctr_drbg_init( &ctr_drbg ); #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold( DEBUG_LEVEL ); #endif /* * 1. Load the certificates and private RSA key */ printf( "\n . Loading the server cert. and key..." ); fflush( stdout ); /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); /* * 2. Setup the "listening" UDP socket */ printf( " . Bind on udp/*/4433 ..." ); fflush( stdout ); if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 ) { printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } printf( " ok\n" ); /* * 3. Seed the RNG */ printf( " . Seeding the random number generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } printf( " ok\n" ); /* * 4. Setup stuff */ printf( " . Setting up the DTLS data..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) { printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_cookie_setup( &cookie_ctx, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { printf( " failed\n ! mbedtls_ssl_cookie_setup returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_dtls_cookies( &conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &cookie_ctx ); if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay ); printf( " ok\n" ); reset: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); printf("Last error was: %d - %s\n\n", ret, error_buf ); } #endif mbedtls_net_free( &client_fd ); mbedtls_ssl_session_reset( &ssl ); /* * 3. Wait until a client connects */ printf( " . Waiting for a remote connection ..." ); fflush( stdout ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, client_ip, sizeof( client_ip ), &cliip_len ) ) != 0 ) { printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } /* For HelloVerifyRequest cookies */ if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl, client_ip, cliip_len ) ) != 0 ) { printf( " failed\n ! " "mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", -ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout ); printf( " ok\n" ); /* * 5. Handshake */ printf( " . Performing the DTLS handshake..." ); fflush( stdout ); do ret = mbedtls_ssl_handshake( &ssl ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ); if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) { printf( " hello verification requested\n" ); ret = 0; goto reset; } else if( ret != 0 ) { printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto reset; } printf( " ok\n" ); /* * 6. Read the echo Request */ printf( " < Read from client:" ); fflush( stdout ); len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); do ret = mbedtls_ssl_read( &ssl, buf, len ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ); if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_TIMEOUT: printf( " timeout\n\n" ); goto reset; case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: printf( " connection was closed gracefully\n" ); ret = 0; goto close_notify; default: printf( " mbedtls_ssl_read returned -0x%x\n\n", -ret ); goto reset; } } len = ret; printf( " %d bytes read\n\n%s\n\n", len, buf ); /* * 7. Write the 200 Response */ printf( " > Write to client:" ); fflush( stdout ); do ret = mbedtls_ssl_write( &ssl, buf, len ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ); if( ret < 0 ) { printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } len = ret; printf( " %d bytes written\n\n%s\n\n", len, buf ); /* * 8. Done, cleanly close the connection */ close_notify: printf( " . Closing the connection..." ); /* No error checking, the connection might be closed already */ do ret = mbedtls_ssl_close_notify( &ssl ); while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); ret = 0; printf( " done\n" ); goto reset; /* * Final clean-ups and exit */ exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); printf( "Last error was: %d - %s\n\n", ret, error_buf ); } #endif mbedtls_net_free( &client_fd ); mbedtls_net_free( &listen_fd ); mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ssl_cookie_free( &cookie_ctx ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif /* Shell can not handle large exit numbers -> 1 for errors */ if( ret < 0 ) ret = 1; return( ret ); }
static void free_pkey( value v ){ mbedtls_pk_context *k = val_pkey(v); mbedtls_pk_free(k); }
void kaa_deinit_rsa_keypair(void) { mbedtls_pk_free(&kaa_pk_context_); }
int main( int argc, char *argv[] ) { int ret = 0; mbedtls_pk_context key; char buf[1024]; int i; char *p, *q; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; const char *pers = "gen_key"; #if defined(MBEDTLS_ECP_C) const mbedtls_ecp_curve_info *curve_info; #endif /* * Set to sane values */ mbedtls_pk_init( &key ); mbedtls_ctr_drbg_init( &ctr_drbg ); memset( buf, 0, sizeof( buf ) ); if( argc == 0 ) { usage: ret = 1; mbedtls_printf( USAGE ); #if defined(MBEDTLS_ECP_C) mbedtls_printf( " available ec_curve values:\n" ); curve_info = mbedtls_ecp_curve_list(); mbedtls_printf( " %s (default)\n", curve_info->name ); while( ( ++curve_info )->name != NULL ) mbedtls_printf( " %s\n", curve_info->name ); #endif goto exit; } opt.type = DFL_TYPE; opt.rsa_keysize = DFL_RSA_KEYSIZE; opt.ec_curve = DFL_EC_CURVE; opt.filename = DFL_FILENAME; opt.format = DFL_FORMAT; opt.use_dev_random = DFL_USE_DEV_RANDOM; for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "type" ) == 0 ) { if( strcmp( q, "rsa" ) == 0 ) opt.type = MBEDTLS_PK_RSA; else if( strcmp( q, "ec" ) == 0 ) opt.type = MBEDTLS_PK_ECKEY; else goto usage; } else if( strcmp( p, "format" ) == 0 ) { if( strcmp( q, "pem" ) == 0 ) opt.format = FORMAT_PEM; else if( strcmp( q, "der" ) == 0 ) opt.format = FORMAT_DER; else goto usage; } else if( strcmp( p, "rsa_keysize" ) == 0 ) { opt.rsa_keysize = atoi( q ); if( opt.rsa_keysize < 1024 || opt.rsa_keysize > MBEDTLS_MPI_MAX_BITS ) goto usage; } #if defined(MBEDTLS_ECP_C) else if( strcmp( p, "ec_curve" ) == 0 ) { if( ( curve_info = mbedtls_ecp_curve_info_from_name( q ) ) == NULL ) goto usage; opt.ec_curve = curve_info->grp_id; } #endif else if( strcmp( p, "filename" ) == 0 ) opt.filename = q; else if( strcmp( p, "use_dev_random" ) == 0 ) { opt.use_dev_random = atoi( q ); if( opt.use_dev_random < 0 || opt.use_dev_random > 1 ) goto usage; } else goto usage; } mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); #if !defined(_WIN32) && defined(MBEDTLS_FS_IO) if( opt.use_dev_random ) { if( ( ret = mbedtls_entropy_add_source( &entropy, dev_random_entropy_poll, NULL, DEV_RANDOM_THRESHOLD, MBEDTLS_ENTROPY_SOURCE_STRONG ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_entropy_add_source returned -0x%04x\n", -ret ); goto exit; } mbedtls_printf("\n Using /dev/random, so can take a long time! " ); fflush( stdout ); } #endif /* !_WIN32 && MBEDTLS_FS_IO */ if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret ); goto exit; } /* * 1.1. Generate the key */ mbedtls_printf( "\n . Generating the private key ..." ); fflush( stdout ); if( ( ret = mbedtls_pk_setup( &key, mbedtls_pk_info_from_type( opt.type ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_setup returned -0x%04x", -ret ); goto exit; } #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME) if( opt.type == MBEDTLS_PK_RSA ) { ret = mbedtls_rsa_gen_key( mbedtls_pk_rsa( key ), mbedtls_ctr_drbg_random, &ctr_drbg, opt.rsa_keysize, 65537 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_rsa_gen_key returned -0x%04x", -ret ); goto exit; } } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) if( opt.type == MBEDTLS_PK_ECKEY ) { ret = mbedtls_ecp_gen_key( opt.ec_curve, mbedtls_pk_ec( key ), mbedtls_ctr_drbg_random, &ctr_drbg ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_rsa_gen_key returned -0x%04x", -ret ); goto exit; } } else #endif /* MBEDTLS_ECP_C */ { mbedtls_printf( " failed\n ! key type not supported\n" ); goto exit; } /* * 1.2 Print the key */ mbedtls_printf( " ok\n . Key information:\n" ); #if defined(MBEDTLS_RSA_C) if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_RSA ) { mbedtls_rsa_context *rsa = mbedtls_pk_rsa( key ); mbedtls_mpi_write_file( "N: ", &rsa->N, 16, NULL ); mbedtls_mpi_write_file( "E: ", &rsa->E, 16, NULL ); mbedtls_mpi_write_file( "D: ", &rsa->D, 16, NULL ); mbedtls_mpi_write_file( "P: ", &rsa->P, 16, NULL ); mbedtls_mpi_write_file( "Q: ", &rsa->Q, 16, NULL ); mbedtls_mpi_write_file( "DP: ", &rsa->DP, 16, NULL ); mbedtls_mpi_write_file( "DQ: ", &rsa->DQ, 16, NULL ); mbedtls_mpi_write_file( "QP: ", &rsa->QP, 16, NULL ); } else #endif #if defined(MBEDTLS_ECP_C) if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_ECKEY ) { mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( key ); mbedtls_printf( "curve: %s\n", mbedtls_ecp_curve_info_from_grp_id( ecp->grp.id )->name ); mbedtls_mpi_write_file( "X_Q: ", &ecp->Q.X, 16, NULL ); mbedtls_mpi_write_file( "Y_Q: ", &ecp->Q.Y, 16, NULL ); mbedtls_mpi_write_file( "D: ", &ecp->d , 16, NULL ); } else #endif mbedtls_printf(" ! key type not supported\n"); /* * 1.3 Export key */ mbedtls_printf( " . Writing key to file..." ); if( ( ret = write_private_key( &key, opt.filename ) ) != 0 ) { mbedtls_printf( " failed\n" ); goto exit; } mbedtls_printf( " ok\n" ); exit: if( ret != 0 && ret != 1) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror( ret, buf, sizeof( buf ) ); mbedtls_printf( " - %s\n", buf ); #else mbedtls_printf("\n"); #endif } mbedtls_pk_free( &key ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, char *argv[] ) { FILE *f; int ret = 1; mbedtls_pk_context pk; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; unsigned char hash[32]; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; char filename[512]; const char *pers = "rsa_sign_pss"; size_t olen = 0; mbedtls_entropy_init( &entropy ); mbedtls_pk_init( &pk ); mbedtls_ctr_drbg_init( &ctr_drbg ); if( argc != 3 ) { mbedtls_printf( "usage: rsa_sign_pss <key_file> <filename>\n" ); #if defined(_WIN32) mbedtls_printf( "\n" ); #endif goto exit; } mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( "\n . Reading private key from '%s'", argv[1] ); fflush( stdout ); if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 ) { ret = 1; mbedtls_printf( " failed\n ! Could not read key from '%s'\n", argv[1] ); mbedtls_printf( " ! mbedtls_pk_parse_public_keyfile returned %d\n\n", ret ); goto exit; } if( !mbedtls_pk_can_do( &pk, MBEDTLS_PK_RSA ) ) { ret = 1; mbedtls_printf( " failed\n ! Key is not an RSA key\n" ); goto exit; } mbedtls_rsa_set_padding( mbedtls_pk_rsa( pk ), MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256 ); /* * Compute the SHA-256 hash of the input file, * then calculate the RSA signature of the hash. */ mbedtls_printf( "\n . Generating the RSA/SHA-256 signature" ); fflush( stdout ); if( ( ret = mbedtls_md_file( mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), argv[2], hash ) ) != 0 ) { mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); goto exit; } if( ( ret = mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, 0, buf, &olen, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_sign returned %d\n\n", ret ); goto exit; } /* * Write the signature into <filename>.sig */ mbedtls_snprintf( filename, 512, "%s.sig", argv[2] ); if( ( f = fopen( filename, "wb+" ) ) == NULL ) { ret = 1; mbedtls_printf( " failed\n ! Could not create %s\n\n", filename ); goto exit; } if( fwrite( buf, 1, olen, f ) != olen ) { mbedtls_printf( "failed\n ! fwrite failed\n\n" ); goto exit; } fclose( f ); mbedtls_printf( "\n . Done (created \"%s\")\n\n", filename ); exit: mbedtls_pk_free( &pk ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
void PKey::clear() { if (mbedtls_pk_get_type(&m_key)) mbedtls_pk_free(&m_key); }
int main( int argc, char *argv[] ) { FILE *f; int ret = 1; int exit_code = MBEDTLS_EXIT_FAILURE; mbedtls_pk_context pk; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; unsigned char hash[32]; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; char filename[512]; const char *pers = "mbedtls_pk_sign"; size_t olen = 0; mbedtls_entropy_init( &entropy ); mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_pk_init( &pk ); if( argc != 3 ) { mbedtls_printf( "usage: mbedtls_pk_sign <key_file> <filename>\n" ); #if defined(_WIN32) mbedtls_printf( "\n" ); #endif goto exit; } mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret ); goto exit; } mbedtls_printf( "\n . Reading private key from '%s'", argv[1] ); fflush( stdout ); if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 ) { mbedtls_printf( " failed\n ! Could not parse '%s'\n", argv[1] ); goto exit; } /* * Compute the SHA-256 hash of the input file, * then calculate the signature of the hash. */ mbedtls_printf( "\n . Generating the SHA-256 signature" ); fflush( stdout ); if( ( ret = mbedtls_md_file( mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), argv[2], hash ) ) != 0 ) { mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); goto exit; } if( ( ret = mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, 0, buf, &olen, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_sign returned -0x%04x\n", -ret ); goto exit; } /* * Write the signature into <filename>.sig */ mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[2] ); if( ( f = fopen( filename, "wb+" ) ) == NULL ) { mbedtls_printf( " failed\n ! Could not create %s\n\n", filename ); goto exit; } if( fwrite( buf, 1, olen, f ) != olen ) { mbedtls_printf( "failed\n ! fwrite failed\n\n" ); fclose( f ); goto exit; } fclose( f ); mbedtls_printf( "\n . Done (created \"%s\")\n\n", filename ); exit_code = MBEDTLS_EXIT_SUCCESS; exit: mbedtls_pk_free( &pk ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(MBEDTLS_ERROR_C) if( exit_code != MBEDTLS_EXIT_SUCCESS ) { mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); mbedtls_printf( " ! Last error was: %s\n", buf ); } #endif #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( exit_code ); }
void reset(context& d) noexcept { d.key_is_private_ = false; mbedtls_pk_free(&d.pk_); }
/* * Verify a signature. * * Parameters are passed using the DER encoding format following the ASN.1 * structures detailed above. */ static int verify_signature(void *data_ptr, unsigned int data_len, void *sig_ptr, unsigned int sig_len, void *sig_alg, unsigned int sig_alg_len, void *pk_ptr, unsigned int pk_len) { mbedtls_asn1_buf sig_oid, sig_params; mbedtls_asn1_buf signature; mbedtls_md_type_t md_alg; mbedtls_pk_type_t pk_alg; mbedtls_pk_context pk; int rc; void *sig_opts = NULL; const mbedtls_md_info_t *md_info; unsigned char *p, *end; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; /* Get pointers to signature OID and parameters */ p = (unsigned char *)sig_alg; end = (unsigned char *)(p + sig_alg_len); rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); if (rc != 0) { return CRYPTO_ERR_SIGNATURE; } /* Get the actual signature algorithm (MD + PK) */ rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); if (rc != 0) { return CRYPTO_ERR_SIGNATURE; } /* Parse the public key */ mbedtls_pk_init(&pk); p = (unsigned char *)pk_ptr; end = (unsigned char *)(p + pk_len); rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); if (rc != 0) { return CRYPTO_ERR_SIGNATURE; } /* Get the signature (bitstring) */ p = (unsigned char *)sig_ptr; end = (unsigned char *)(p + sig_len); signature.tag = *p; rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); if (rc != 0) { rc = CRYPTO_ERR_SIGNATURE; goto end; } signature.p = p; /* Calculate the hash of the data */ md_info = mbedtls_md_info_from_type(md_alg); if (md_info == NULL) { rc = CRYPTO_ERR_SIGNATURE; goto end; } p = (unsigned char *)data_ptr; rc = mbedtls_md(md_info, p, data_len, hash); if (rc != 0) { rc = CRYPTO_ERR_SIGNATURE; goto end; } /* Verify the signature */ rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, mbedtls_md_get_size(md_info), signature.p, signature.len); if (rc != 0) { rc = CRYPTO_ERR_SIGNATURE; goto end; } /* Signature verification success */ rc = CRYPTO_SUCCESS; end: mbedtls_pk_free(&pk); return rc; }
/******************************************************************************* * Asymmetric ciphers * *******************************************************************************/ int __attribute__((weak)) wrapped_asym_keygen(Cipher c, CryptoKey key_type, uint8_t* pub, size_t* pub_len, uint8_t* priv, size_t* priv_len) { if (keygen_deferred_handling(key_type)) { // If overriden by user implementation. return _keygen_overrides[key_type](c, key_type, pub, pub_len, priv, priv_len); } int ret = -1; mbedtls_pk_context key; mbedtls_pk_init(&key); uint32_t pers = randomInt(); mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ctr_drbg_init(&ctr_drbg); ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const uint8_t*) &pers, 4 ); if (0 == ret) { switch (c) { #if defined(WRAPPED_ASYM_RSA) case Cipher::ASYM_RSA: { ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)); if (0 == ret) { mbedtls_rsa_context* rsa = mbedtls_pk_rsa(key); ret = mbedtls_rsa_gen_key(rsa, mbedtls_ctr_drbg_random, &ctr_drbg, (int) key_type, 65537 ); if (0 == ret) { ret--; memset(pub, 0, *pub_len); memset(priv, 0, *priv_len); int written = mbedtls_pk_write_pubkey_der(&key, pub, *pub_len); if (0 < written) { *pub_len = written; written = mbedtls_pk_write_key_der(&key, priv, *priv_len); if (0 < written) { *priv_len = written; ret = 0; } } } } } break; #endif #if defined(MBEDTLS_ECDSA_C) case Cipher::ASYM_ECDSA: { ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)); if (0 == ret) { mbedtls_ecp_keypair* ec_kp = mbedtls_pk_ec(key); ret = mbedtls_ecdsa_genkey(ec_kp, (mbedtls_ecp_group_id) key_type, mbedtls_ctr_drbg_random, &ctr_drbg ); if (0 == ret) { ret--; memset(pub, 0, *pub_len); memset(priv, 0, *priv_len); int written = mbedtls_pk_write_pubkey_der(&key, pub, *pub_len); if (0 < written) { *pub_len = written; written = mbedtls_pk_write_key_der(&key, priv, *priv_len); if (0 < written) { *priv_len = written; ret = 0; } } } } } break; #endif #if defined(MBEDTLS_ECP_C) case Cipher::ASYM_ECKEY: { ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)); if (0 == ret) { mbedtls_ecp_keypair* ec_kp = mbedtls_pk_ec(key); ret = mbedtls_ecp_gen_key( (mbedtls_ecp_group_id) key_type, ec_kp, mbedtls_ctr_drbg_random, &ctr_drbg ); if (0 == ret) { ret--; memset(pub, 0, *pub_len); memset(priv, 0, *priv_len); int written = mbedtls_pk_write_pubkey_der(&key, pub, *pub_len); if (0 < written) { *pub_len = written; written = mbedtls_pk_write_key_der(&key, priv, *priv_len); if (0 < written) { *priv_len = written; ret = 0; } } } } } break; #endif default: break; } } mbedtls_pk_free(&key); mbedtls_ctr_drbg_free(&ctr_drbg); return ret; }
int main( void ) { int ret; mbedtls_net_context listen_fd, client_fd; const char pers[] = "ssl_pthread_server"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_x509_crt cachain; mbedtls_pk_context pkey; #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) unsigned char alloc_buf[100000]; #endif #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) ); #endif #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_x509_crt_init( &cachain ); mbedtls_ssl_config_init( &conf ); mbedtls_ctr_drbg_init( &ctr_drbg ); memset( threads, 0, sizeof(threads) ); mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_mutex_init( &debug_mutex ); base_info.config = &conf; /* * We use only a single entropy source that is used in all the threads. */ mbedtls_entropy_init( &entropy ); /* * 1. Load the certificates and private RSA key */ mbedtls_printf( "\n . Loading the server cert. and key..." ); fflush( stdout ); /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &cachain, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } mbedtls_pk_init( &pkey ); ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1b. Seed the random number generator */ mbedtls_printf( " . Seeding the random number generator..." ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed: mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1c. Prepare SSL configuration */ mbedtls_printf( " . Setting up the SSL data...." ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed: mbedtls_ssl_config_defaults returned -0x%04x\n", -ret ); goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_mutexed_debug, stdout ); /* mbedtls_ssl_cache_get() and mbedtls_ssl_cache_set() are thread-safe if * MBEDTLS_THREADING_C is set. */ #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif mbedtls_ssl_conf_ca_chain( &conf, &cachain, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Setup the listening TCP socket */ mbedtls_printf( " . Bind on https://localhost:4433/ ..." ); fflush( stdout ); if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); reset: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf( " [ main ] Last error was: -0x%04x - %s\n", -ret, error_buf ); } #endif /* * 3. Wait until a client connects */ mbedtls_printf( " [ main ] Waiting for a remote connection\n" ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " [ main ] failed: mbedtls_net_accept returned -0x%04x\n", ret ); goto exit; } mbedtls_printf( " [ main ] ok\n" ); mbedtls_printf( " [ main ] Creating a new thread\n" ); if( ( ret = thread_create( &client_fd ) ) != 0 ) { mbedtls_printf( " [ main ] failed: thread_create returned %d\n", ret ); mbedtls_net_free( &client_fd ); goto reset; } ret = 0; goto reset; exit: mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); mbedtls_ssl_config_free( &conf ); mbedtls_net_free( &listen_fd ); mbedtls_mutex_free( &debug_mutex ); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_free(); #endif #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * Parse an unencrypted PKCS#8 encoded private key */ static int pk_parse_key_pkcs8_unencrypted_der( mbedtls_pk_context *pk, const unsigned char* key, size_t keylen ) { int ret, version; size_t len; mbedtls_asn1_buf params; unsigned char *p = (unsigned char *) key; unsigned char *end = p + keylen; mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; const mbedtls_pk_info_t *pk_info; /* * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) * * PrivateKeyInfo ::= SEQUENCE { * version Version, * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, * privateKey PrivateKey, * attributes [0] IMPLICIT Attributes OPTIONAL } * * Version ::= INTEGER * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier * PrivateKey ::= OCTET STRING * * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey */ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); } end = p + len; if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); if( version != 0 ) return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); if( len < 1 ) return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) return( ret ); #if defined(MBEDTLS_RSA_C) if( pk_alg == MBEDTLS_PK_RSA ) { if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) { mbedtls_pk_free( pk ); return( ret ); } } else #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) { if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) { mbedtls_pk_free( pk ); return( ret ); } } else #endif /* MBEDTLS_ECP_C */ return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); return( 0 ); }
int main( int argc, const char *argv[] ) { /* Client and server declarations. */ int ret; int len; #if SOCKET_COMMUNICATION mbedtls_net_context listen_fd, client_fd, server_fd; #endif unsigned char buf[1024]; /* Handshake step counter */ size_t step = 1; int flags; mbedtls_ssl_context s_ssl, c_ssl; mbedtls_ssl_config s_conf, c_conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif if( argc == 3) { packet_in_num = atoi(argv[1]); packet_in_file = argv[2]; } else if( argc != 1) { usage(argv[0]); exit(1); } /* Server init */ #if SOCKET_COMMUNICATION mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); #endif mbedtls_ssl_init( &s_ssl ); mbedtls_ssl_config_init( &s_conf ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_pk_init( &pkey ); /* Client init */ #if SOCKET_COMMUNICATION mbedtls_net_init( &server_fd ); #endif mbedtls_ssl_init( &c_ssl ); mbedtls_ssl_config_init( &c_conf ); /*mbedtls_x509_crt_init( &cacert );*/ #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold( DEBUG_LEVEL ); #endif /* * Server: * Load the certificates and private RSA key */ if( packet_in_num == 0 ) { mbedtls_printf( " . Loading the server cert. and key..." ); fflush( stdout ); } /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * Setup stuff */ if( packet_in_num == 0 ) { mbedtls_printf( " . Server: Setting up the SSL data...." ); fflush( stdout ); } if( ( ret = mbedtls_ssl_config_defaults( &s_conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_rng( &s_conf, mbedtls_ctr_drbg_deterministic, NULL ); mbedtls_ssl_conf_dbg( &s_conf, my_debug, stdout ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &s_conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif mbedtls_ssl_conf_ca_chain( &s_conf, srvcert.next, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &s_conf, &srvcert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &s_ssl, &s_conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } mbedtls_ssl_session_reset( &s_ssl ); #if SOCKET_COMMUNICATION /* * Server: * Setup the listening TCP socket */ if( packet_in_num == 0 ) { mbedtls_printf( " . Bind on https://localhost:%s/ ...", SERVER_PORT ); fflush( stdout ); } if( ( ret = mbedtls_net_bind( &listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Client: * Start the connection */ if( packet_in_num == 0 ) { mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT ); fflush( stdout ); } if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * Start listening for client connections */ if( packet_in_num == 0 ) { mbedtls_printf( " . Waiting for a remote connection ..." ); fflush( stdout ); } /* * Server: * Accept client connection (socket is set non-blocking in * library/net.c) */ if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } mbedtls_ssl_set_bio( &s_ssl, &client_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL ); #else mbedtls_ssl_set_bio( &s_ssl, NULL, mbedtls_server_send_buf, mbedtls_server_recv_buf, NULL ); #endif /* * Client: * Setup stuff */ if( packet_in_num == 0 ) { mbedtls_printf( " . Client: Setting up the SSL/TLS structure..." ); fflush( stdout ); } if( ( ret = mbedtls_ssl_config_defaults( &c_conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* OPTIONAL is not optimal for security, * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); /* NONE permits man-in-the-middle attacks. */ /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_NONE );*/ /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_REQUIRED );*/ mbedtls_ssl_conf_ca_chain( &c_conf, &srvcert, NULL ); mbedtls_ssl_conf_rng( &c_conf, mbedtls_ctr_drbg_deterministic, NULL ); mbedtls_ssl_conf_dbg( &c_conf, my_debug, stdout ); if( ( ret = mbedtls_ssl_setup( &c_ssl, &c_conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_set_hostname( &c_ssl, "mbed TLS Server 1" ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); goto exit; } #if SOCKET_COMMUNICATION mbedtls_ssl_set_bio( &c_ssl, &server_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL ); #else mbedtls_ssl_set_bio( &c_ssl, NULL, mbedtls_client_send_buf, mbedtls_client_recv_buf, NULL ); #endif if( packet_in_num == 0 ) { mbedtls_printf( " . Performing the SSL/TLS handshake...\n" ); fflush( stdout ); } /* * The following number of steps are hardcoded to ensure * that the client and server complete the handshake without * waiting infinitely for the other side to send data. * * 1 2 3 4 5 6 7 8 9 10 */ int client_steps[] = { 2, 1, 1, 1, 4, 2, 1, 1, 2, 1 }; int server_steps[] = { 3, 1, 1, 2, 3, 1, 2, 1, 1, 1 }; do { /* * Client: * Handshake step */ int i; int no_steps; if( c_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { no_steps = 0; } else { no_steps = client_steps[step - 1]; } for (i = 0; i < no_steps; i++) { if( ( ret = mbedtls_ssl_handshake_step( &c_ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto exit; } } } if( packet_in_num == 0 ) { mbedtls_printf( "--- client handshake step %zd ok\n", step ); } /* * Server: * Handshake step */ if( s_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { no_steps = 0; } else { no_steps = server_steps[step - 1]; } for (i = 0; i < no_steps; i++) { if( ( ret = mbedtls_ssl_handshake_step( &s_ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret ); goto exit; } } } if( packet_in_num == 0 ) { mbedtls_printf( "--- server handshake step %zd ok\n", step ); } step++; } while( ((c_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) || (s_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)) && (step <= MAX_HANDSHAKE_STEPS) ); if( packet_in_num == 0 ) { mbedtls_printf( "c_ssl.state: %d\n", c_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER ); mbedtls_printf( "s_ssl.state: %d\n", s_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER ); } /* * Client: * Verify the server certificate */ if( packet_in_num == 0 ) { mbedtls_printf( " . Verifying peer X.509 certificate..." ); } /* In real life, we probably want to bail out when ret != 0 */ if( ( flags = mbedtls_ssl_get_verify_result( &c_ssl ) ) != 0 ) { char vrfy_buf[512]; mbedtls_printf( " failed\n" ); mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); mbedtls_printf( "%s\n", vrfy_buf ); } else if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Client: * Write the GET request */ if( packet_in_num == 0 ) { mbedtls_printf( " > Write to server:" ); fflush( stdout ); } len = sprintf( (char *) buf, GET_REQUEST ); while( ( ret = mbedtls_ssl_write( &c_ssl, buf, len ) ) <= 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes written\n\n%s", len, (char *) buf ); } /* * Server: * Read the HTTP Request */ if( packet_in_num == 0 ) { mbedtls_printf( " < Read from client:" ); fflush( stdout ); } do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &s_ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " connection was closed gracefully\n" ); break; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( " connection was reset by peer\n" ); break; default: mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); break; } break; } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); } if( ret > 0 ) break; } while( 1 ); /* * Server: * Write the 200 Response */ if( packet_in_num == 0 ) { mbedtls_printf( " > Write to client:" ); fflush( stdout ); } len = sprintf( (char *) buf, HTTP_RESPONSE, mbedtls_ssl_get_ciphersuite( &s_ssl ) ); while( ( ret = mbedtls_ssl_write( &s_ssl, buf, len ) ) <= 0 ) { if( ret == MBEDTLS_ERR_NET_CONN_RESET ) { mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); goto exit; } if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf ); } /* * Client: * Read the HTTP response */ if( packet_in_num == 0 ) { mbedtls_printf( " < Read from server:" ); fflush( stdout ); } do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &c_ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) { ret = 0; break; } if( ret < 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret ); break; } if( ret == 0 ) { mbedtls_printf( "\n\nEOF\n\n" ); break; } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); } /* * Server: * Client read response. Close connection. */ if ( packet_in_num == 0 ) { mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); } while( ( ret = mbedtls_ssl_close_notify( &s_ssl ) ) < 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_close_notify returned %d\n\n", ret ); goto exit; } } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } } while( 1 ); /* * Client: * Close connection. */ if( packet_in_num == 0 ) { mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); } mbedtls_ssl_close_notify( &c_ssl ); if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * We do not have multiple clients and therefore do not goto reset. */ /*ret = 0;*/ /*goto reset;*/ exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); } #endif #if SOCKET_COMMUNICATION mbedtls_net_free( &client_fd ); mbedtls_net_free( &listen_fd ); mbedtls_net_free( &server_fd ); #endif mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &s_ssl ); mbedtls_ssl_free( &c_ssl ); mbedtls_ssl_config_free( &s_conf ); mbedtls_ssl_config_free( &c_conf ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, char *argv[] ) { int ret = 0; mbedtls_pk_context key; char buf[1024]; int i; char *p, *q; /* * Set to sane values */ mbedtls_pk_init( &key ); memset( buf, 0, sizeof( buf ) ); if( argc == 0 ) { usage: ret = 1; mbedtls_printf( USAGE ); goto exit; } opt.mode = DFL_MODE; opt.filename = DFL_FILENAME; opt.output_mode = DFL_OUTPUT_MODE; opt.output_file = DFL_OUTPUT_FILENAME; opt.output_format = DFL_OUTPUT_FORMAT; for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "mode" ) == 0 ) { if( strcmp( q, "private" ) == 0 ) opt.mode = MODE_PRIVATE; else if( strcmp( q, "public" ) == 0 ) opt.mode = MODE_PUBLIC; else goto usage; } else if( strcmp( p, "output_mode" ) == 0 ) { if( strcmp( q, "private" ) == 0 ) opt.output_mode = OUTPUT_MODE_PRIVATE; else if( strcmp( q, "public" ) == 0 ) opt.output_mode = OUTPUT_MODE_PUBLIC; else goto usage; } else if( strcmp( p, "output_format" ) == 0 ) { #if defined(MBEDTLS_PEM_WRITE_C) if( strcmp( q, "pem" ) == 0 ) opt.output_format = OUTPUT_FORMAT_PEM; else #endif if( strcmp( q, "der" ) == 0 ) opt.output_format = OUTPUT_FORMAT_DER; else goto usage; } else if( strcmp( p, "filename" ) == 0 ) opt.filename = q; else if( strcmp( p, "output_file" ) == 0 ) opt.output_file = q; else goto usage; } if( opt.mode == MODE_NONE && opt.output_mode != OUTPUT_MODE_NONE ) { mbedtls_printf( "\nCannot output a key without reading one.\n"); goto exit; } if( opt.mode == MODE_PUBLIC && opt.output_mode == OUTPUT_MODE_PRIVATE ) { mbedtls_printf( "\nCannot output a private key from a public key.\n"); goto exit; } if( opt.mode == MODE_PRIVATE ) { /* * 1.1. Load the key */ mbedtls_printf( "\n . Loading the private key ..." ); fflush( stdout ); ret = mbedtls_pk_parse_keyfile( &key, opt.filename, NULL ); if( ret != 0 ) { mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1.2 Print the key */ mbedtls_printf( " . Key information ...\n" ); #if defined(MBEDTLS_RSA_C) if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_RSA ) { mbedtls_rsa_context *rsa = mbedtls_pk_rsa( key ); mbedtls_mpi_write_file( "N: ", &rsa->N, 16, NULL ); mbedtls_mpi_write_file( "E: ", &rsa->E, 16, NULL ); mbedtls_mpi_write_file( "D: ", &rsa->D, 16, NULL ); mbedtls_mpi_write_file( "P: ", &rsa->P, 16, NULL ); mbedtls_mpi_write_file( "Q: ", &rsa->Q, 16, NULL ); mbedtls_mpi_write_file( "DP: ", &rsa->DP, 16, NULL ); mbedtls_mpi_write_file( "DQ: ", &rsa->DQ, 16, NULL ); mbedtls_mpi_write_file( "QP: ", &rsa->QP, 16, NULL ); } else #endif #if defined(MBEDTLS_ECP_C) if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_ECKEY ) { mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( key ); mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ); mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ); mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ); mbedtls_mpi_write_file( "D : ", &ecp->d , 16, NULL ); } else #endif mbedtls_printf("key type not supported yet\n"); } else if( opt.mode == MODE_PUBLIC ) { /* * 1.1. Load the key */ mbedtls_printf( "\n . Loading the public key ..." ); fflush( stdout ); ret = mbedtls_pk_parse_public_keyfile( &key, opt.filename ); if( ret != 0 ) { mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); mbedtls_printf( " failed\n ! mbedtls_pk_parse_public_key returned -0x%04x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1.2 Print the key */ mbedtls_printf( " . Key information ...\n" ); #if defined(MBEDTLS_RSA_C) if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_RSA ) { mbedtls_rsa_context *rsa = mbedtls_pk_rsa( key ); mbedtls_mpi_write_file( "N: ", &rsa->N, 16, NULL ); mbedtls_mpi_write_file( "E: ", &rsa->E, 16, NULL ); } else #endif #if defined(MBEDTLS_ECP_C) if( mbedtls_pk_get_type( &key ) == MBEDTLS_PK_ECKEY ) { mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( key ); mbedtls_mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL ); mbedtls_mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL ); mbedtls_mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL ); } else #endif mbedtls_printf("key type not supported yet\n"); } else goto usage; if( opt.output_mode == OUTPUT_MODE_PUBLIC ) { write_public_key( &key, opt.output_file ); } if( opt.output_mode == OUTPUT_MODE_PRIVATE ) { write_private_key( &key, opt.output_file ); } exit: if( ret != 0 && ret != 1) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror( ret, buf, sizeof( buf ) ); mbedtls_printf( " - %s\n", buf ); #else mbedtls_printf("\n"); #endif } mbedtls_pk_free( &key ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
void clax_loop_ssl(clax_ctx_t *clax_ctx) { int ret = 0; char pers[] = "clax_server"; #ifdef MVS clax_etoa(pers, strlen(pers)); #endif mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; mbedtls_ssl_cache_context cache; mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_ssl_cache_init(&cache); mbedtls_x509_crt_init(&srvcert); mbedtls_pk_init(&pkey); mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&ctr_drbg); #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(DEBUG_LEVEL); #endif clax_log("Loading the server cert and key..."); unsigned char *file = NULL; size_t file_len = 0; clax_log("Loading '%s'...", options.cert_file); file = clax_slurp_alloc(options.cert_file, &file_len); if (file == NULL) { clax_log("Can't load cert_file '%s': %s", options.cert_file, strerror(errno)); goto exit; } #ifdef MVS clax_etoa((char *)file, file_len); #endif clax_log("Parsing '%s'...", options.cert_file); ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *)file, file_len); free(file); if (ret != 0) { clax_log("failed\n ! mbedtls_x509_crt_parse returned %d", ret); goto exit; } clax_log("Loading '%s'...", options.key_file); file = clax_slurp_alloc(options.key_file, &file_len); if (file == NULL) { clax_log("Can't load key_file: %s", options.key_file); goto exit; } #ifdef MVS clax_etoa((char *)file, file_len); #endif clax_log("Parsing '%s'...", options.key_file); ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *)file, file_len, NULL, 0); free(file); if (ret != 0) { clax_log("failed\n ! mbedtls_pk_parse_key returned %d", ret); goto exit; } clax_log("ok"); if (options.entropy_file[0]) { clax_log("Using '%s' as entropy file...", options.entropy_file); if ((ret = mbedtls_entropy_add_source(&entropy, dev_random_entropy_poll, NULL, DEV_RANDOM_THRESHOLD, MBEDTLS_ENTROPY_SOURCE_STRONG)) != 0) { clax_log("failed\n ! mbedtls_entropy_add_source returned -0x%04x", -ret); goto exit; } clax_log("ok"); } clax_log("Seeding the random number generator..."); if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers))) != 0) { clax_log("failed\n ! mbedtls_ctr_drbg_seed returned %d", ret); goto exit; } clax_log("ok"); clax_log("Setting up the SSL data...."); if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { clax_log("failed\n ! mbedtls_ssl_config_defaults returned %d", ret); goto exit; } if (!options.no_ssl_verify) { mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); } mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_session_cache(&conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set); mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL); if ((ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey)) != 0) { clax_log(" failed\n ! mbedtls_ssl_conf_own_cert returned %d", ret); goto exit; } if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { clax_log(" failed\n ! mbedtls_ssl_setup returned %d", ret); goto exit; } clax_log("ok"); mbedtls_ssl_session_reset(&ssl); mbedtls_ssl_set_bio(&ssl, NULL, clax_send, clax_recv, NULL); clax_log("ok"); clax_log("Performing the SSL/TLS handshake..."); while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { clax_log("failed\n ! mbedtls_ssl_handshake returned %d", ret); goto exit; } } clax_log("ok"); clax_http_dispatch(clax_ctx, clax_send_ssl, clax_recv_ssl, &ssl); clax_log("Closing the connection..."); while ((ret = mbedtls_ssl_close_notify(&ssl)) < 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { clax_log("failed\n ! mbedtls_ssl_close_notify returned %d", ret); goto exit; } } clax_log("ok"); ret = 0; goto exit; exit: fflush(stdout); #ifdef MBEDTLS_ERROR_C if (ret != 0) { char error_buf[100]; mbedtls_strerror(ret, error_buf, 100); #ifdef MVS clax_atoe(error_buf, strlen(error_buf)); #endif clax_log("Last error was: %d - %s", ret, error_buf); } #endif mbedtls_x509_crt_free(&srvcert); mbedtls_pk_free(&pkey); mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ssl_cache_free(&cache); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); }
int main( int argc, char *argv[] ) { FILE *f; int ret = 1, c; int exit_code = MBEDTLS_EXIT_FAILURE; size_t i, olen = 0; mbedtls_pk_context pk; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; unsigned char result[1024]; unsigned char buf[512]; const char *pers = "mbedtls_pk_decrypt"; ((void) argv); mbedtls_pk_init( &pk ); mbedtls_entropy_init( &entropy ); mbedtls_ctr_drbg_init( &ctr_drbg ); memset(result, 0, sizeof( result ) ); if( argc != 2 ) { mbedtls_printf( "usage: mbedtls_pk_decrypt <key_file>\n" ); #if defined(_WIN32) mbedtls_printf( "\n" ); #endif goto exit; } mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret ); goto exit; } mbedtls_printf( "\n . Reading private key from '%s'", argv[1] ); fflush( stdout ); if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret ); goto exit; } /* * Extract the RSA encrypted value from the text file */ if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL ) { mbedtls_printf( "\n ! Could not open %s\n\n", "result-enc.txt" ); ret = 1; goto exit; } i = 0; while( fscanf( f, "%02X", &c ) > 0 && i < (int) sizeof( buf ) ) { buf[i++] = (unsigned char) c; } fclose( f ); /* * Decrypt the encrypted RSA data and print the result. */ mbedtls_printf( "\n . Decrypting the encrypted data" ); fflush( stdout ); if( ( ret = mbedtls_pk_decrypt( &pk, buf, i, result, &olen, sizeof(result), mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_decrypt returned -0x%04x\n", -ret ); goto exit; } mbedtls_printf( "\n . OK\n\n" ); mbedtls_printf( "The decrypted result is: '%s'\n\n", result ); exit_code = MBEDTLS_EXIT_SUCCESS; exit: mbedtls_pk_free( &pk ); mbedtls_entropy_free( &entropy ); mbedtls_ctr_drbg_free( &ctr_drbg ); #if defined(MBEDTLS_ERROR_C) if( exit_code != MBEDTLS_EXIT_SUCCESS ) { mbedtls_strerror( ret, (char *) buf, sizeof( buf ) ); mbedtls_printf( " ! Last error was: %s\n", buf ); } #endif #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( exit_code ); }
int main( void ) { int ret, len, cnt = 0, pid; mbedtls_net_context listen_fd, client_fd; unsigned char buf[1024]; const char *pers = "ssl_fork_server"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); mbedtls_entropy_init( &entropy ); mbedtls_pk_init( &pkey ); mbedtls_x509_crt_init( &srvcert ); mbedtls_ctr_drbg_init( &ctr_drbg ); signal( SIGCHLD, SIG_IGN ); /* * 0. Initial seeding of the RNG */ mbedtls_printf( "\n . Initial seeding of the random generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1. Load the certificates and private RSA key */ mbedtls_printf( " . Loading the server cert. and key..." ); fflush( stdout ); /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1b. Prepare SSL configuration */ mbedtls_printf( " . Configuring SSL..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Setup the listening TCP socket */ mbedtls_printf( " . Bind on https://localhost:4433/ ..." ); fflush( stdout ); if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); while( 1 ) { /* * 3. Wait until a client connects */ mbedtls_net_init( &client_fd ); mbedtls_ssl_init( &ssl ); mbedtls_printf( " . Waiting for a remote connection ..." ); fflush( stdout ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 3.5. Forking server thread */ pid = fork(); mbedtls_printf( " . Forking to handle connection ..." ); fflush( stdout ); if( pid < 0 ) { mbedtls_printf(" failed\n ! fork returned %d\n\n", pid ); goto exit; } mbedtls_printf( " ok\n" ); if( pid != 0 ) { if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, (const unsigned char *) "parent", 6 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_reseed returned %d\n", ret ); goto exit; } mbedtls_net_free( &client_fd ); continue; } mbedtls_net_free( &listen_fd ); /* * 4. Setup stuff */ mbedtls_printf( " . Setting up the SSL data...." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, (const unsigned char *) "child", 5 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_reseed returned %d\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); mbedtls_printf( " ok\n" ); /* * 5. Handshake */ mbedtls_printf( " . Performing the SSL/TLS handshake..." ); fflush( stdout ); while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret ); goto exit; } } mbedtls_printf( " ok\n" ); /* * 6. Read the HTTP Request */ mbedtls_printf( " < Read from client:" ); fflush( stdout ); do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " connection was closed gracefully\n" ); break; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( " connection was reset by peer\n" ); break; default: mbedtls_printf( " mbedtls_ssl_read returned %d\n", ret ); break; } break; } len = ret; mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); if( ret > 0 ) break; } while( 1 ); /* * 7. Write the 200 Response */ mbedtls_printf( " > Write to client:" ); fflush( stdout ); len = sprintf( (char *) buf, HTTP_RESPONSE, mbedtls_ssl_get_ciphersuite( &ssl ) ); while( cnt++ < 100 ) { while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) { if( ret == MBEDTLS_ERR_NET_CONN_RESET ) { mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); goto exit; } if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf ); mbedtls_net_usleep( 1000000 ); } mbedtls_ssl_close_notify( &ssl ); goto exit; } exit: mbedtls_net_free( &client_fd ); mbedtls_net_free( &listen_fd ); mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * CSR is output formatted as b64url(DER) * Private key is output as a PEM in memory */ LWS_VISIBLE LWS_EXTERN int lws_tls_acme_sni_csr_create(struct lws_context *context, const char *elements[], uint8_t *dcsr, size_t csr_len, char **privkey_pem, size_t *privkey_len) { mbedtls_x509write_csr csr; char subject[200]; mbedtls_pk_context mpk; int buf_size = 4096, n; uint8_t *buf = malloc(buf_size); /* malloc because given to user code */ if (!buf) return -1; mbedtls_x509write_csr_init(&csr); mbedtls_pk_init(&mpk); if (mbedtls_pk_setup(&mpk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA))) { lwsl_notice("%s: pk_setup failed\n", __func__); goto fail; } n = mbedtls_rsa_gen_key(mbedtls_pk_rsa(mpk), _rngf, context, lws_plat_recommended_rsa_bits(), 65537); if (n) { lwsl_notice("%s: failed to generate keys\n", __func__); goto fail1; } /* subject must be formatted like "C=TW,O=warmcat,CN=myserver" */ lws_snprintf(subject, sizeof(subject) - 1, "C=%s,ST=%s,L=%s,O=%s,CN=%s", elements[LWS_TLS_REQ_ELEMENT_COUNTRY], elements[LWS_TLS_REQ_ELEMENT_STATE], elements[LWS_TLS_REQ_ELEMENT_LOCALITY], elements[LWS_TLS_REQ_ELEMENT_ORGANIZATION], elements[LWS_TLS_REQ_ELEMENT_COMMON_NAME]); if (mbedtls_x509write_csr_set_subject_name(&csr, subject)) goto fail1; mbedtls_x509write_csr_set_key(&csr, &mpk); mbedtls_x509write_csr_set_md_alg(&csr, MBEDTLS_MD_SHA256); /* * data is written at the end of the buffer! Use the * return value to determine where you should start * using the buffer */ n = mbedtls_x509write_csr_der(&csr, buf, buf_size, _rngf, context); if (n < 0) { lwsl_notice("%s: write csr der failed\n", __func__); goto fail1; } /* we have it in DER, we need it in b64URL */ n = lws_jws_base64_enc((char *)(buf + buf_size) - n, n, (char *)dcsr, csr_len); if (n < 0) goto fail1; /* * okay, the CSR is done, last we need the private key in PEM * re-use the DER CSR buf as the result buffer since we cn do it in * one step */ if (mbedtls_pk_write_key_pem(&mpk, buf, buf_size)) { lwsl_notice("write key pem failed\n"); goto fail1; } *privkey_pem = (char *)buf; *privkey_len = strlen((const char *)buf); mbedtls_pk_free(&mpk); mbedtls_x509write_csr_free(&csr); return n; fail1: mbedtls_pk_free(&mpk); fail: mbedtls_x509write_csr_free(&csr); free(buf); return -1; }
int main( int argc, char *argv[] ) { int ret = 0; mbedtls_x509_crt issuer_crt; mbedtls_pk_context loaded_issuer_key, loaded_subject_key; mbedtls_pk_context *issuer_key = &loaded_issuer_key, *subject_key = &loaded_subject_key; char buf[1024]; char issuer_name[128]; int i; char *p, *q, *r; #if defined(MBEDTLS_X509_CSR_PARSE_C) char subject_name[128]; mbedtls_x509_csr csr; #endif mbedtls_x509write_cert crt; mbedtls_mpi serial; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; const char *pers = "crt example app"; /* * Set to sane values */ mbedtls_x509write_crt_init( &crt ); mbedtls_x509write_crt_set_md_alg( &crt, MBEDTLS_MD_SHA256 ); mbedtls_pk_init( &loaded_issuer_key ); mbedtls_pk_init( &loaded_subject_key ); mbedtls_mpi_init( &serial ); mbedtls_ctr_drbg_init( &ctr_drbg ); #if defined(MBEDTLS_X509_CSR_PARSE_C) mbedtls_x509_csr_init( &csr ); #endif mbedtls_x509_crt_init( &issuer_crt ); memset( buf, 0, 1024 ); if( argc == 0 ) { usage: mbedtls_printf( USAGE ); ret = 1; goto exit; } opt.issuer_crt = DFL_ISSUER_CRT; 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'; 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 |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE; else if( strcmp( q, "non_repudiation" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION; else if( strcmp( q, "key_encipherment" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT; else if( strcmp( q, "data_encipherment" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT; else if( strcmp( q, "key_agreement" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT; else if( strcmp( q, "key_cert_sign" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN; else if( strcmp( q, "crl_sign" ) == 0 ) opt.key_usage |= MBEDTLS_X509_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 |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT; else if( strcmp( q, "ssl_server" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER; else if( strcmp( q, "email" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL; else if( strcmp( q, "object_signing" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING; else if( strcmp( q, "ssl_ca" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA; else if( strcmp( q, "email_ca" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA; else if( strcmp( q, "object_signing_ca" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA; else goto usage; q = r; } } else goto usage; } mbedtls_printf("\n"); /* * 0. Seed the PRNG */ mbedtls_printf( " . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d - %s\n", ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); // Parse serial to MPI // mbedtls_printf( " . Reading serial number..." ); fflush( stdout ); if( ( ret = mbedtls_mpi_read_string( &serial, 10, opt.serial ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_mpi_read_string returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); // Parse issuer certificate if present // if( !opt.selfsign && strlen( opt.issuer_crt ) ) { /* * 1.0.a. Load the certificates */ mbedtls_printf( " . Loading the issuer certificate ..." ); fflush( stdout ); if( ( ret = mbedtls_x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name), &issuer_crt.subject ); if( ret < 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } opt.issuer_name = issuer_name; mbedtls_printf( " ok\n" ); } #if defined(MBEDTLS_X509_CSR_PARSE_C) // Parse certificate request if present // if( !opt.selfsign && strlen( opt.request_file ) ) { /* * 1.0.b. Load the CSR */ mbedtls_printf( " . Loading the certificate request ..." ); fflush( stdout ); if( ( ret = mbedtls_x509_csr_parse_file( &csr, opt.request_file ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509_csr_parse_file returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } ret = mbedtls_x509_dn_gets( subject_name, sizeof(subject_name), &csr.subject ); if( ret < 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } opt.subject_name = subject_name; subject_key = &csr.pk; mbedtls_printf( " ok\n" ); } #endif /* MBEDTLS_X509_CSR_PARSE_C */ /* * 1.1. Load the keys */ if( !opt.selfsign && !strlen( opt.request_file ) ) { mbedtls_printf( " . Loading the subject key ..." ); fflush( stdout ); ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key, opt.subject_pwd ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); } mbedtls_printf( " . Loading the issuer key ..." ); fflush( stdout ); ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key, opt.issuer_pwd ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_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( !mbedtls_pk_can_do( &issuer_crt.pk, MBEDTLS_PK_RSA ) || mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->N, &mbedtls_pk_rsa( *issuer_key )->N ) != 0 || mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->E, &mbedtls_pk_rsa( *issuer_key )->E ) != 0 ) { mbedtls_printf( " failed\n ! issuer_key does not match issuer certificate\n\n" ); ret = -1; goto exit; } } mbedtls_printf( " ok\n" ); if( opt.selfsign ) { opt.subject_name = opt.issuer_name; subject_key = issuer_key; } mbedtls_x509write_crt_set_subject_key( &crt, subject_key ); mbedtls_x509write_crt_set_issuer_key( &crt, issuer_key ); /* * 1.0. Check the names for validity */ if( ( ret = mbedtls_x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject_name returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } if( ( ret = mbedtls_x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_issuer_name returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " . Setting certificate values ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_serial( &crt, &serial ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_serial returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } ret = mbedtls_x509write_crt_set_validity( &crt, opt.not_before, opt.not_after ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_validity returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); mbedtls_printf( " . Adding the Basic Constraints extension ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_basic_constraints( &crt, opt.is_ca, opt.max_pathlen ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! x509write_crt_set_basic_contraints returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); #if defined(MBEDTLS_SHA1_C) mbedtls_printf( " . Adding the Subject Key Identifier ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_subject_key_identifier( &crt ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); mbedtls_printf( " . Adding the Authority Key Identifier ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_authority_key_identifier( &crt ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_authority_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); #endif /* MBEDTLS_SHA1_C */ if( opt.key_usage ) { mbedtls_printf( " . Adding the Key Usage extension ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_key_usage( &crt, opt.key_usage ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_key_usage returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); } if( opt.ns_cert_type ) { mbedtls_printf( " . Adding the NS Cert Type extension ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_ns_cert_type returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); } /* * 1.2. Writing the request */ mbedtls_printf( " . Writing the certificate..." ); fflush( stdout ); if( ( ret = write_certificate( &crt, opt.output_file, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! write_certifcate -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); exit: mbedtls_x509write_crt_free( &crt ); mbedtls_pk_free( &loaded_subject_key ); mbedtls_pk_free( &loaded_issuer_key ); mbedtls_mpi_free( &serial ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, char *argv[] ) { int ret = 1, len; int exit_code = MBEDTLS_EXIT_FAILURE; mbedtls_net_context server_fd; unsigned char buf[1024]; #if defined(MBEDTLS_BASE64_C) unsigned char base[1024]; #endif char hostname[32]; const char *pers = "ssl_mail_client"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; mbedtls_x509_crt clicert; mbedtls_pk_context pkey; int i; size_t n; char *p, *q; const int *list; /* * Make sure memory references are valid in case we exit early. */ mbedtls_net_init( &server_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); memset( &buf, 0, sizeof( buf ) ); mbedtls_x509_crt_init( &cacert ); mbedtls_x509_crt_init( &clicert ); mbedtls_pk_init( &pkey ); mbedtls_ctr_drbg_init( &ctr_drbg ); if( argc == 0 ) { usage: mbedtls_printf( USAGE ); list = mbedtls_ssl_list_ciphersuites(); while( *list ) { mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) ); list++; } mbedtls_printf("\n"); goto exit; } opt.server_name = DFL_SERVER_NAME; opt.server_port = DFL_SERVER_PORT; opt.debug_level = DFL_DEBUG_LEVEL; opt.authentication = DFL_AUTHENTICATION; opt.mode = DFL_MODE; opt.user_name = DFL_USER_NAME; opt.user_pwd = DFL_USER_PWD; opt.mail_from = DFL_MAIL_FROM; opt.mail_to = DFL_MAIL_TO; opt.ca_file = DFL_CA_FILE; opt.crt_file = DFL_CRT_FILE; opt.key_file = DFL_KEY_FILE; opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "server_name" ) == 0 ) opt.server_name = q; else if( strcmp( p, "server_port" ) == 0 ) opt.server_port = q; else if( strcmp( p, "debug_level" ) == 0 ) { opt.debug_level = atoi( q ); if( opt.debug_level < 0 || opt.debug_level > 65535 ) goto usage; } else if( strcmp( p, "authentication" ) == 0 ) { opt.authentication = atoi( q ); if( opt.authentication < 0 || opt.authentication > 1 ) goto usage; } else if( strcmp( p, "mode" ) == 0 ) { opt.mode = atoi( q ); if( opt.mode < 0 || opt.mode > 1 ) goto usage; } else if( strcmp( p, "user_name" ) == 0 ) opt.user_name = q; else if( strcmp( p, "user_pwd" ) == 0 ) opt.user_pwd = q; else if( strcmp( p, "mail_from" ) == 0 ) opt.mail_from = q; else if( strcmp( p, "mail_to" ) == 0 ) opt.mail_to = q; else if( strcmp( p, "ca_file" ) == 0 ) opt.ca_file = q; else if( strcmp( p, "crt_file" ) == 0 ) opt.crt_file = q; else if( strcmp( p, "key_file" ) == 0 ) opt.key_file = q; else if( strcmp( p, "force_ciphersuite" ) == 0 ) { opt.force_ciphersuite[0] = -1; opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); if( opt.force_ciphersuite[0] <= 0 ) goto usage; opt.force_ciphersuite[1] = 0; } else goto usage; } /* * 0. Initialize the RNG and the session data */ mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1.1. Load the trusted CA */ mbedtls_printf( " . Loading the CA root certificate ..." ); fflush( stdout ); #if defined(MBEDTLS_FS_IO) if( strlen( opt.ca_file ) ) ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ); else #endif #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_PEM_PARSE_C) ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); #else { mbedtls_printf("MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C not defined."); goto exit; } #endif if( ret < 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok (%d skipped)\n", ret ); /* * 1.2. Load own certificate and private key * * (can be skipped if client authentication is not required) */ mbedtls_printf( " . Loading the client cert. and key..." ); fflush( stdout ); #if defined(MBEDTLS_FS_IO) if( strlen( opt.crt_file ) ) ret = mbedtls_x509_crt_parse_file( &clicert, opt.crt_file ); else #endif #if defined(MBEDTLS_CERTS_C) ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, mbedtls_test_cli_crt_len ); #else { mbedtls_printf("MBEDTLS_CERTS_C not defined."); goto exit; } #endif if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } #if defined(MBEDTLS_FS_IO) if( strlen( opt.key_file ) ) ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "" ); else #endif #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_PEM_PARSE_C) ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_cli_key, mbedtls_test_cli_key_len, NULL, 0 ); #else { mbedtls_printf("MBEDTLS_CERTS_C or MBEDTLS_PEM_PARSE_C not defined."); goto exit; } #endif if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Start the connection */ mbedtls_printf( " . Connecting to tcp/%s/%s...", opt.server_name, opt.server_port ); fflush( stdout ); if( ( ret = mbedtls_net_connect( &server_fd, opt.server_name, opt.server_port, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 3. Setup stuff */ mbedtls_printf( " . Setting up the SSL/TLS structure..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } /* OPTIONAL is not optimal for security, * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite ); mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); mbedtls_printf( " ok\n" ); if( opt.mode == MODE_SSL_TLS ) { if( do_handshake( &ssl ) != 0 ) goto exit; mbedtls_printf( " > Get header from server:" ); fflush( stdout ); ret = write_ssl_and_get_response( &ssl, buf, 0 ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write EHLO to server:" ); fflush( stdout ); gethostname( hostname, 32 ); len = sprintf( (char *) buf, "EHLO %s\r\n", hostname ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } } else { mbedtls_printf( " > Get header from server:" ); fflush( stdout ); ret = write_and_get_response( &server_fd, buf, 0 ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write EHLO to server:" ); fflush( stdout ); gethostname( hostname, 32 ); len = sprintf( (char *) buf, "EHLO %s\r\n", hostname ); ret = write_and_get_response( &server_fd, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write STARTTLS to server:" ); fflush( stdout ); gethostname( hostname, 32 ); len = sprintf( (char *) buf, "STARTTLS\r\n" ); ret = write_and_get_response( &server_fd, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); if( do_handshake( &ssl ) != 0 ) goto exit; } #if defined(MBEDTLS_BASE64_C) if( opt.authentication ) { mbedtls_printf( " > Write AUTH LOGIN to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "AUTH LOGIN\r\n" ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write username to server: %s", opt.user_name ); fflush( stdout ); ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_name, strlen( opt.user_name ) ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret ); goto exit; } len = sprintf( (char *) buf, "%s\r\n", base ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 300 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write password to server: %s", opt.user_pwd ); fflush( stdout ); ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_pwd, strlen( opt.user_pwd ) ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret ); goto exit; } len = sprintf( (char *) buf, "%s\r\n", base ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); } #endif mbedtls_printf( " > Write MAIL FROM to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "MAIL FROM:<%s>\r\n", opt.mail_from ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write RCPT TO to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "RCPT TO:<%s>\r\n", opt.mail_to ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write DATA to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "DATA\r\n" ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 300 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write content to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "From: %s\r\nSubject: mbed TLS Test mail\r\n\r\n" "This is a simple test mail from the " "mbed TLS mail client example.\r\n" "\r\n" "Enjoy!", opt.mail_from ); ret = write_ssl_data( &ssl, buf, len ); len = sprintf( (char *) buf, "\r\n.\r\n"); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_ssl_close_notify( &ssl ); exit_code = MBEDTLS_EXIT_SUCCESS; exit: mbedtls_net_free( &server_fd ); mbedtls_x509_crt_free( &clicert ); mbedtls_x509_crt_free( &cacert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( exit_code ); }
ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { ssh_key key = NULL; mbedtls_pk_context *rsa = NULL; mbedtls_pk_context *ecdsa = NULL; ed25519_privkey *ed25519 = NULL; enum ssh_keytypes_e type; int valid; /* mbedtls pk_parse_key expects strlen to count the 0 byte */ size_t b64len = strlen(b64_key) + 1; unsigned char tmp[MAX_PASSPHRASE_SIZE] = {0}; type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key."); return NULL; } switch (type) { case SSH_KEYTYPE_RSA: rsa = malloc(sizeof(mbedtls_pk_context)); if (rsa == NULL) { return NULL; } mbedtls_pk_init(rsa); if (passphrase == NULL) { if (auth_fn) { valid = auth_fn("Passphrase for private key:", (char *) tmp, MAX_PASSPHRASE_SIZE, 0, 0, auth_data); if (valid < 0) { return NULL; } /* TODO fix signedness and strlen */ valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); } else { valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, NULL, 0); } } else { valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); } if (valid != 0) { char error_buf[100]; mbedtls_strerror(valid, error_buf, 100); SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); goto fail; } break; case SSH_KEYTYPE_ECDSA: ecdsa = malloc(sizeof(mbedtls_pk_context)); if (ecdsa == NULL) { return NULL; } mbedtls_pk_init(ecdsa); if (passphrase == NULL) { if (auth_fn) { valid = auth_fn("Passphrase for private key:", (char *) tmp, MAX_PASSPHRASE_SIZE, 0, 0, auth_data); if (valid < 0) { return NULL; } valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); } else { valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, NULL, 0); } } else { valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); } if (valid != 0) { char error_buf[100]; mbedtls_strerror(valid, error_buf, 100); SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); goto fail; } break; case SSH_KEYTYPE_ED25519: /* Cannot open ed25519 keys with libmbedcrypto */ default: SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type); return NULL; } key = ssh_key_new(); if (key == NULL) { goto fail; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->rsa = rsa; if (ecdsa != NULL) { mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*ecdsa); key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context)); if (key->ecdsa == NULL) { goto fail; } mbedtls_ecdsa_init(key->ecdsa); mbedtls_ecdsa_from_keypair(key->ecdsa, keypair); mbedtls_pk_free(ecdsa); SAFE_FREE(ecdsa); } else { key->ecdsa = NULL; } key->ed25519_privkey = ed25519; rsa = NULL; ecdsa = NULL; if (key->type == SSH_KEYTYPE_ECDSA) { key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); key->type_c = pki_key_ecdsa_nid_to_name(key->ecdsa_nid); } return key; fail: ssh_key_free(key); if (rsa != NULL) { mbedtls_pk_free(rsa); SAFE_FREE(rsa); } if (ecdsa != NULL) { mbedtls_pk_free(ecdsa); SAFE_FREE(ecdsa); } return NULL; }
STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { // Verify the socket object has the full stream protocol mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); #if MICROPY_PY_USSL_FINALISER mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t); #else mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t); #endif o->base.type = &ussl_socket_type; o->sock = sock; int ret; mbedtls_ssl_init(&o->ssl); mbedtls_ssl_config_init(&o->conf); mbedtls_x509_crt_init(&o->cacert); mbedtls_x509_crt_init(&o->cert); mbedtls_pk_init(&o->pkey); mbedtls_ctr_drbg_init(&o->ctr_drbg); #ifdef MBEDTLS_DEBUG_C // Debug level (0-4) mbedtls_debug_set_threshold(0); #endif mbedtls_entropy_init(&o->entropy); const byte seed[] = "upy"; ret = mbedtls_ctr_drbg_seed(&o->ctr_drbg, mbedtls_entropy_func, &o->entropy, seed, sizeof(seed)); if (ret != 0) { goto cleanup; } ret = mbedtls_ssl_config_defaults(&o->conf, args->server_side.u_bool ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { goto cleanup; } mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg); #ifdef MBEDTLS_DEBUG_C mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL); #endif ret = mbedtls_ssl_setup(&o->ssl, &o->conf); if (ret != 0) { goto cleanup; } if (args->server_hostname.u_obj != mp_const_none) { const char *sni = mp_obj_str_get_str(args->server_hostname.u_obj); ret = mbedtls_ssl_set_hostname(&o->ssl, sni); if (ret != 0) { goto cleanup; } } mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL); if (args->key.u_obj != MP_OBJ_NULL) { size_t key_len; const byte *key = (const byte*)mp_obj_str_get_data(args->key.u_obj, &key_len); // len should include terminating null ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0); assert(ret == 0); size_t cert_len; const byte *cert = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &cert_len); // len should include terminating null ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1); assert(ret == 0); ret = mbedtls_ssl_conf_own_cert(&o->conf, &o->cert, &o->pkey); assert(ret == 0); } if (args->do_handshake.u_bool) { while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { printf("mbedtls_ssl_handshake error: -%x\n", -ret); goto cleanup; } } } return o; cleanup: mbedtls_pk_free(&o->pkey); mbedtls_x509_crt_free(&o->cert); mbedtls_x509_crt_free(&o->cacert); mbedtls_ssl_free(&o->ssl); mbedtls_ssl_config_free(&o->conf); mbedtls_ctr_drbg_free(&o->ctr_drbg); mbedtls_entropy_free(&o->entropy); if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) { mp_raise_OSError(MP_ENOMEM); } else { mp_raise_OSError(MP_EIO); } }
/* * Parse a private key */ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, const unsigned char *key, size_t keylen, const unsigned char *pwd, size_t pwdlen ) { int ret; const mbedtls_pk_info_t *pk_info; #if defined(MBEDTLS_PEM_PARSE_C) size_t len; mbedtls_pem_context pem; mbedtls_pem_init( &pem ); #if defined(MBEDTLS_RSA_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if( keylen == 0 || key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----", key, pwd, pwdlen, &len ); if( ret == 0 ) { if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), pem.buf, pem.buflen ) ) != 0 ) { mbedtls_pk_free( pk ); } mbedtls_pem_free( &pem ); return( ret ); } else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if( keylen == 0 || key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, "-----BEGIN EC PRIVATE KEY-----", "-----END EC PRIVATE KEY-----", key, pwd, pwdlen, &len ); if( ret == 0 ) { if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), pem.buf, pem.buflen ) ) != 0 ) { mbedtls_pk_free( pk ); } mbedtls_pem_free( &pem ); return( ret ); } else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); #endif /* MBEDTLS_ECP_C */ /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if( keylen == 0 || key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, "-----BEGIN PRIVATE KEY-----", "-----END PRIVATE KEY-----", key, NULL, 0, &len ); if( ret == 0 ) { if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, pem.buf, pem.buflen ) ) != 0 ) { mbedtls_pk_free( pk ); } mbedtls_pem_free( &pem ); return( ret ); } else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if( keylen == 0 || key[keylen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, "-----BEGIN ENCRYPTED PRIVATE KEY-----", "-----END ENCRYPTED PRIVATE KEY-----", key, NULL, 0, &len ); if( ret == 0 ) { if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, pem.buf, pem.buflen, pwd, pwdlen ) ) != 0 ) { mbedtls_pk_free( pk ); } mbedtls_pem_free( &pem ); return( ret ); } else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) return( ret ); #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ #else ((void) ret); ((void) pwd); ((void) pwdlen); #endif /* MBEDTLS_PEM_PARSE_C */ /* * At this point we only know it's not a PEM formatted key. Could be any * of the known DER encoded private key formats * * We try the different DER format parsers to see if one passes without * error */ #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, pwd, pwdlen ) ) == 0 ) { return( 0 ); } mbedtls_pk_free( pk ); if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) { return( ret ); } #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) return( 0 ); mbedtls_pk_free( pk ); #if defined(MBEDTLS_RSA_C) if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 ) { return( 0 ); } mbedtls_pk_free( pk ); #endif /* MBEDTLS_RSA_C */ #if defined(MBEDTLS_ECP_C) if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), key, keylen ) ) == 0 ) { return( 0 ); } mbedtls_pk_free( pk ); #endif /* MBEDTLS_ECP_C */ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); }
int main( int argc, char *argv[] ) { FILE *f; int ret = 1; size_t i; mbedtls_pk_context pk; unsigned char hash[20]; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; char filename[512]; mbedtls_pk_init( &pk ); if( argc != 3 ) { mbedtls_printf( "usage: mbedtls_pk_verify <key_file> <filename>\n" ); #if defined(_WIN32) mbedtls_printf( "\n" ); #endif goto exit; } mbedtls_printf( "\n . Reading public key from '%s'", argv[1] ); fflush( stdout ); if( ( ret = mbedtls_pk_parse_public_keyfile( &pk, argv[1] ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret ); goto exit; } /* * Extract the signature from the text file */ ret = 1; mbedtls_snprintf( filename, sizeof(filename), "%s.sig", argv[2] ); if( ( f = fopen( filename, "rb" ) ) == NULL ) { mbedtls_printf( "\n ! Could not open %s\n\n", filename ); goto exit; } i = fread( buf, 1, sizeof(buf), f ); fclose( f ); /* * Compute the SHA-256 hash of the input file and compare * it with the hash decrypted from the signature. */ mbedtls_printf( "\n . Verifying the SHA-256 signature" ); fflush( stdout ); if( ( ret = mbedtls_md_file( mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), argv[2], hash ) ) != 0 ) { mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); goto exit; } if( ( ret = mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, hash, 0, buf, i ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_verify returned -0x%04x\n", -ret ); goto exit; } mbedtls_printf( "\n . OK (the decrypted SHA-256 hash matches)\n\n" ); ret = 0; exit: mbedtls_pk_free( &pk ); #if defined(MBEDTLS_ERROR_C) mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); mbedtls_printf( " ! Last error was: %s\n", buf ); #endif #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }