Crypto modes: CBC, CFB, ECB.
Not ready to link into build yet.

Delta says 1272 lines but only 474
if you subtract the test files,
which are mostly data.

R=r
DELTA=1252  (1249 added, 0 deleted, 3 changed)
OCL=29013
CL=29037
diff --git a/src/lib/io/io.go b/src/lib/io/io.go
index 91b6ffd..c120d8d 100644
--- a/src/lib/io/io.go
+++ b/src/lib/io/io.go
@@ -27,6 +27,9 @@
 
 
 // Reader is the interface that wraps the basic Read method.
+// An implementation of Read is allowed to use all of p for
+// scratch space during the call, even if it eventually returns
+// n < len(p).
 type Reader interface {
 	Read(p []byte) (n int, err os.Error);
 }
@@ -80,10 +83,11 @@
 	return w.Write(StringBytes(s))
 }
 
-// FullRead reads r until the buffer buf is full, or until EOF or error.
-func FullRead(r Reader, buf []byte) (n int, err os.Error) {
+// ReadAtLeast reads r into buf until at least min bytes have been read,
+// or until EOF or error.
+func ReadAtLeast(r Reader, buf []byte, min int) (n int, err os.Error) {
 	n = 0;
-	for n < len(buf) {
+	for n < min {
 		nn, e := r.Read(buf[n:len(buf)]);
 		if nn > 0 {
 			n += nn
@@ -98,6 +102,13 @@
 	return n, nil
 }
 
+// FullRead reads r until the buffer buf is full, or until EOF or error.
+func FullRead(r Reader, buf []byte) (n int, err os.Error) {
+	// TODO(rsc): 6g bug prevents obvious return
+	n, err = ReadAtLeast(r, buf, len(buf));
+	return;
+}
+
 // Convert something that implements Read into something
 // whose Reads are always FullReads
 type fullRead struct {