Ejemplo n.º 1
0
/*
 * Non-public function wrapped by ctr_crbg_init(). Necessary to allow NIST
 * tests to succeed (which require known length fixed entropy)
 */
int ctr_drbg_init_entropy_len(
                   ctr_drbg_context *ctx,
                   int (*f_entropy)(void *, unsigned char *, size_t),
                   void *p_entropy,
                   const unsigned char *custom,
                   size_t len,
                   size_t entropy_len )
{
    int ret;
    unsigned char key[CTR_DRBG_KEYSIZE];

    memset( ctx, 0, sizeof(ctr_drbg_context) );
    memset( key, 0, CTR_DRBG_KEYSIZE );

    ctx->f_entropy = f_entropy;
    ctx->p_entropy = p_entropy;

    ctx->entropy_len = entropy_len;
    ctx->reseed_interval = CTR_DRBG_RESEED_INTERVAL;

    /*
     * Initialize with an empty key
     */
    aes_setkey_enc( &ctx->aes_ctx, key, CTR_DRBG_KEYBITS );

    if( ( ret = ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
        return( ret );

    return( 0 );
}
Ejemplo n.º 2
0
int rand_ctx_reseed()
{
  ctr_drbg_context *cd_ctx = rand_ctx_get();
  entropy_context *ec = cd_ctx->p_entropy;

  ASSERT(NULL != ec);

  if (!entropy_gather_blocking(ec))
    return 0;
  if (0 != ctr_drbg_reseed(cd_ctx, NULL, 0))
    return 0;

  return 1;
}
Ejemplo n.º 3
0
/* Push new entropy into the CTR_DRBG instance in ctx, combining
 * it with the entropy already there.  On success, 0 is returned.  If
 * the callback returns a non-zero value, that value is returned.
 * Other errors return -1.
 */
static int
fips_drbg_reseed(struct fips_drbg_ctx_s *ctx)
{
	uint8_t entropy_pool[Q_HW_DRBG_BLOCK_BYTES];
	int rv;
	enum ctr_drbg_status_t init_rv;

	if (ctx == NULL)
		return FIPS140_PRNG_ERR;

	if (!ctx->fips_drbg_started) {
		rv = (*ctx->get_entropy_callback)(ctx->get_entropy_callback_ctx,
			ctx->prev_hw_drbg_block
			);
		if (rv != 0)
			return FIPS140_PRNG_ERR;
		ctx->fips_drbg_started = 1;
	}

	rv = (*ctx->get_entropy_callback)(ctx->get_entropy_callback_ctx,
		entropy_pool
		);
	if (rv != 0) {
		memset(entropy_pool, 0, Q_HW_DRBG_BLOCK_BYTES);
		return FIPS140_PRNG_ERR;
	}

	if (!memcmp(entropy_pool,
			ctx->prev_hw_drbg_block,
			Q_HW_DRBG_BLOCK_BYTES)) {
		memset(entropy_pool, 0, Q_HW_DRBG_BLOCK_BYTES);
		return FIPS140_PRNG_ERR;
	} else
		memcpy(ctx->prev_hw_drbg_block,
				entropy_pool,
				Q_HW_DRBG_BLOCK_BYTES);

	init_rv = ctr_drbg_reseed(&ctx->ctr_drbg_ctx,
				entropy_pool,
				8*MSM_ENTROPY_BUFFER_SIZE);

	/* Zeroize the buffer for security. */
	memset(entropy_pool, 0, Q_HW_DRBG_BLOCK_BYTES);

	return (init_rv == CTR_DRBG_SUCCESS ?
				FIPS140_PRNG_OK :
				FIPS140_PRNG_ERR);
}
Ejemplo n.º 4
0
/*
 * Checkup routine
 */
int ctr_drbg_self_test( int verbose )
{
    ctr_drbg_context ctx;
    unsigned char buf[16];

    /*
     * Based on a NIST CTR_DRBG test vector (PR = True)
     */
    if( verbose != 0 )
        polarssl_printf( "  CTR_DRBG (PR = TRUE) : " );

    test_offset = 0;
    CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
                                entropy_source_pr, nonce_pers_pr, 16, 32 ) );
    ctr_drbg_set_prediction_resistance( &ctx, CTR_DRBG_PR_ON );
    CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
    CHK( ctr_drbg_random( &ctx, buf, CTR_DRBG_BLOCKSIZE ) );
    CHK( memcmp( buf, result_pr, CTR_DRBG_BLOCKSIZE ) );

    if( verbose != 0 )
        polarssl_printf( "passed\n" );

    /*
     * Based on a NIST CTR_DRBG test vector (PR = FALSE)
     */
    if( verbose != 0 )
        polarssl_printf( "  CTR_DRBG (PR = FALSE): " );

    test_offset = 0;
    CHK( ctr_drbg_init_entropy_len( &ctx, ctr_drbg_self_test_entropy,
                            entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
    CHK( ctr_drbg_random( &ctx, buf, 16 ) );
    CHK( ctr_drbg_reseed( &ctx, NULL, 0 ) );
    CHK( ctr_drbg_random( &ctx, buf, 16 ) );
    CHK( memcmp( buf, result_nopr, 16 ) );

    if( verbose != 0 )
        polarssl_printf( "passed\n" );

    if( verbose != 0 )
            polarssl_printf( "\n" );

    return( 0 );
}
Ejemplo n.º 5
0
int ctr_drbg_random_with_add( void *p_rng,
                              unsigned char *output, size_t output_len,
                              const unsigned char *additional, size_t add_len )
{
    int ret = 0;
    ctr_drbg_context *ctx = (ctr_drbg_context *) p_rng;
    unsigned char add_input[CTR_DRBG_SEEDLEN];
    unsigned char *p = output;
    unsigned char tmp[CTR_DRBG_BLOCKSIZE];
    int i;
    size_t use_len;

    if( output_len > CTR_DRBG_MAX_REQUEST )
        return( POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG );

    if( add_len > CTR_DRBG_MAX_INPUT )
        return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG );

    memset( add_input, 0, CTR_DRBG_SEEDLEN );

    if( ctx->reseed_counter > ctx->reseed_interval ||
        ctx->prediction_resistance )
    {
        if( ( ret = ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
            return( ret );

        add_len = 0;
    }

    if( add_len > 0 )
    {
        block_cipher_df( add_input, additional, add_len );
        ctr_drbg_update_internal( ctx, add_input );
    }

    while( output_len > 0 )
    {
        /*
         * Increase counter
         */
        for( i = CTR_DRBG_BLOCKSIZE; i > 0; i-- )
            if( ++ctx->counter[i - 1] != 0 )
                break;

        /*
         * Crypt counter block
         */
        aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->counter, tmp );

        use_len = (output_len > CTR_DRBG_BLOCKSIZE ) ? CTR_DRBG_BLOCKSIZE : output_len;
        /*
         * Copy random block to destination
         */
        memcpy( p, tmp, use_len );
        p += use_len;
        output_len -= use_len;
    }

    ctr_drbg_update_internal( ctx, add_input );

    ctx->reseed_counter++;

    return( 0 );
}
int main( int argc, char *argv[] )
{
    int ret, len, cnt = 0, pid;
    int listen_fd;
    int client_fd;
    unsigned char buf[1024];
    const char *pers = "ssl_fork_server";

    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    ssl_context ssl;
    x509_cert srvcert;
    rsa_context rsa;

    ((void) argc);
    ((void) argv);

    signal( SIGCHLD, SIG_IGN );

    /*
     * 0. Initial seeding of the RNG
     */
    printf( "\n  . Initial seeding of the random generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        printf( " failed\n  ! ctr_drbg_init returned %d\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 1. Load the certificates and private RSA key
     */
    printf( "  . Loading the server cert. and key..." );
    fflush( stdout );

    memset( &srvcert, 0, sizeof( x509_cert ) );

    /*
     * This demonstration program uses embedded test certificates.
     * Instead, you may want to use x509parse_crtfile() to read the
     * server and CA certificates, as well as x509parse_keyfile().
     */
    ret = x509parse_crt( &srvcert, (const unsigned char *) test_srv_crt,
                         strlen( test_srv_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    ret = x509parse_crt( &srvcert, (const unsigned char *) test_ca_crt,
                         strlen( test_ca_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_crt returned %d\n\n", ret );
        goto exit;
    }

    rsa_init( &rsa, RSA_PKCS_V15, 0 );
    ret =  x509parse_key( &rsa, (const unsigned char *) test_srv_key,
                          strlen( test_srv_key ), NULL, 0 );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509parse_key returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    /*
     * 2. Setup the listening TCP socket
     */
    printf( "  . Bind on https://localhost:4433/ ..." );
    fflush( stdout );

    if( ( ret = net_bind( &listen_fd, NULL, 4433 ) ) != 0 )
    {
        printf( " failed\n  ! net_bind returned %d\n\n", ret );
        goto exit;
    }

    printf( " ok\n" );

    while( 1 )
    {
        /*
         * 3. Wait until a client connects
         */
        client_fd = -1;
        memset( &ssl, 0, sizeof( ssl ) );

        printf( "  . Waiting for a remote connection ..." );
        fflush( stdout );

        if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
        {
            printf( " failed\n  ! net_accept returned %d\n\n", ret );
            goto exit;
        }

        printf( " ok\n" );

        /*
         * 3.5. Forking server thread
         */

        pid = fork();

        printf( "  . Forking to handle connection ..." );
        fflush( stdout );

        if( pid < 0 )
        {
            printf(" failed\n  ! fork returned %d\n\n", pid );
            goto exit;
        }

        printf( " ok\n" );

        if( pid != 0 )
        {
            if( ( ret = ctr_drbg_reseed( &ctr_drbg,
                                         (const unsigned char *) "parent",
                                         6 ) ) != 0 )
            {
                printf( " failed\n  ! ctr_drbg_reseed returned %d\n", ret );
                goto exit;
            }

            close( client_fd );
            continue;
        }

        close( listen_fd );

        /*
         * 4. Setup stuff
         */
        printf( "  . Setting up the SSL data...." );
        fflush( stdout );

        if( ( ret = ctr_drbg_reseed( &ctr_drbg,
                                     (const unsigned char *) "child",
                                     5 ) ) != 0 )
        {
            printf( " failed\n  ! ctr_drbg_reseed returned %d\n", ret );
            goto exit;
        }

        if( ( ret = ssl_init( &ssl ) ) != 0 )
        {
            printf( " failed\n  ! ssl_init returned %d\n\n", ret );
            goto exit;
        }

        printf( " ok\n" );

        ssl_set_endpoint( &ssl, SSL_IS_SERVER );
        ssl_set_authmode( &ssl, SSL_VERIFY_NONE );

        ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
        ssl_set_dbg( &ssl, my_debug, stdout );
        ssl_set_bio( &ssl, net_recv, &client_fd,
                           net_send, &client_fd );

        ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
        ssl_set_own_cert( &ssl, &srvcert, &rsa );

        /*
         * 5. Handshake
         */
        printf( "  . Performing the SSL/TLS handshake..." );
        fflush( stdout );

        while( ( ret = ssl_handshake( &ssl ) ) != 0 )
        {
            if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
            {
                printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
                goto exit;
            }
        }

        printf( " ok\n" );

        /*
         * 6. Read the HTTP Request
         */
        printf( "  < Read from client:" );
        fflush( stdout );

        do
        {
            len = sizeof( buf ) - 1;
            memset( buf, 0, sizeof( buf ) );
            ret = ssl_read( &ssl, buf, len );

            if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
                continue;

            if( ret <= 0 )
            {
                switch( ret )
                {
                    case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
                        printf( " connection was closed gracefully\n" );
                        break;

                    case POLARSSL_ERR_NET_CONN_RESET:
                        printf( " connection was reset by peer\n" );
                        break;

                    default:
                        printf( " ssl_read returned %d\n", ret );
                        break;
                }

                break;
            }

            len = ret;
            printf( " %d bytes read\n\n%s", len, (char *) buf );
        }
        while( 0 );

        /*
         * 7. Write the 200 Response
         */
        printf( "  > Write to client:" );
        fflush( stdout );

        len = sprintf( (char *) buf, HTTP_RESPONSE,
                ssl_get_ciphersuite( &ssl ) );

        while( cnt < 100 )
        {
            while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
            {
                if( ret == POLARSSL_ERR_NET_CONN_RESET )
                {
                    printf( " failed\n  ! peer closed the connection\n\n" );
                    goto exit;
                }

                if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
                {
                    printf( " failed\n  ! ssl_write returned %d\n\n", ret );
                    goto exit;
                }
            }
            len = ret;
            printf( " %d bytes written\n\n%s\n", len, (char *) buf );

            m_sleep( 1000 );
        }

        ssl_close_notify( &ssl );
        goto exit;
    }

exit:

    net_close( client_fd );
    x509_free( &srvcert );
    rsa_free( &rsa );
    ssl_free( &ssl );

#if defined(_WIN32)
    printf( "  Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}