The reason your while loop didn't stop is because the script is locked inside that while loop. llSleep blocks the script, but your touch_start function never returns. So even though the timer fires, the timer event is sitting in the queue waiting to be processed, and timer() never gets called because the script is still executing the infinite loop in the touch_start function. Try adding some llOwnerSay debug messages, and you'll see what's happening. For instance, add
llOwnerSay("condition = " + (string)condition);
somewhere inside the while loop, and add
llOwnerSay("handling timer event");
inside the timer handler.
In order to make it work, you'll either have to do what Osgeld suggested, which is to make sure the function returns, and doesn't get locked into an endless loop. If you want to use timers, you'll have to do the blinking inside the timer event, and keep count of how many you've done. If you want to do it with a 0.1s timer (not recommended

, but it looks like you want the eyes to blink really fast for 10 seconds)
integer counter = 0;
integer blinkState = 0;
default
{
touch_start(integer total_number)
{
counter = 0;
llSetTimerEvent(0.1);
}
timer()
{
if (blinkState == 0)
{
llSetColor(<0, 0, 0>, ALL_SIDES);
blinkState = 1;
}
else
{
llSetColor(<1, 1, 1>, ALL_SIDES);
blinkState = 0;
}
counter++;
if (counter >= 100) // 10 seconds, 0.1s timer, so that's 100 ticks
{
llSetTimerEvent(0);
}
}
}
With SL's lag, I'm not sure that will be very predictable - it requires the code inside the timer function to execute within 0.1s, with some time left over. But, as a hypothetical example

, that's one way you could do it with a timer.