Like adh32, I use a list of links above the form (since the user hit the submit button, a new page was loaded... that's always announced to users) which go to the error message in question (which is an anchor with no destination actually). I'm using aria-describedby to associate the error message with the label.
(of course the error page has the page <title> saying the form was not submitted, the h1 states there were errors, etc.)
Originally my form idea was, a (invisible) anchor was generated after each "bad" input that could take the user to the next error message (or submit if there are no others) but the back-ender said it was too difficult to bother. on :focus of these invisible anchors, they'd appear so this would also kick butt for sighted-keyboarders too. Would have loved to see that working somewhere : (
Users, if advanced, can use shift-L or whatever for "previous list" to get back to the list, but I wouldn't know if newbies would try this.
Error messages as plain text in a form: some screen readers have a Forms mode, but not all. In Forms Mode, only form controls are read out (when you focus on an input, the associated label and possibly the legend are read out, for example). However I've found that even when in Forms Mode in, say, JAWS, if there's other focusable thingies in there (like anchors), those'll be read out fine, because they have keyboard focus and you can't just ignore those. One reason I made my errors anchors: they were focusable destinations and their anchor text was the error text.
NVDA is really great in Forms because it switches easily and usually automatically between forms mode (which tells you an input is editable and reads back what you type when typing into one) and regular reading mode (whenever it finds plain text, it'll switch... meaning when you hit keys, they've gone back to navigation keys instead of typing keys). This is really nice and JAWS seems clunkier because you usually have to manually move in and out of Forms Mode. But this is version 10 I have, 12 is out and maybe is more intuitive? But version 10 does do aria-describedby so that's nice.
Orca doesn't have a virtual buffer and doesn't have a forms mode that's particularly special: like NVDA it seems to just switch between reading and letting you Edit, but I haven't gotten the hang of getting those to work right... all playing around with the Orca button or something...
Re virtual buffers: if you're using AJAX to report errors, you have to be much more careful. Older readers with virtual buffers (JAWS, Window-Eyes, NVDA for Windows all have virtual buffers) may not know to refresh them just because there was some AJAX call. Newer readers do know, but you'll want to use some of the other ARIA attributes to have the new error messages interrupt the user or move the focus over to the error message or something.
Unfortunately I don't do enough AJAXY widget stuff to be familiar with all the ARIA-stuff out there for this kind of thing, and support is kinda here and there (newest readers are doing pretty good with ARIA... you can keep up with ARIA tests by Jason Kiss at Accessible Culture.org).