Factor out sequence number updates.

Also check for overflow, although it really shouldn't happen.

Change-Id: I34dfe8eaf635aeaa8bef2656fda3cd0bad7e1268
Reviewed-on: https://boringssl-review.googlesource.com/4235
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/err/ssl.errordata b/crypto/err/ssl.errordata
index 2c34dc6..38aa7ed 100644
--- a/crypto/err/ssl.errordata
+++ b/crypto/err/ssl.errordata
@@ -100,6 +100,7 @@
 SSL,function,196,ssl3_prf
 SSL,function,197,ssl3_read_bytes
 SSL,function,198,ssl3_read_n
+SSL,function,267,ssl3_record_sequence_update
 SSL,function,266,ssl3_seal_record
 SSL,function,199,ssl3_send_cert_verify
 SSL,function,200,ssl3_send_certificate_request
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index a45483f..52de0bb 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2446,6 +2446,7 @@
 #define SSL_F_dtls1_process_fragment 264
 #define SSL_F_dtls1_hm_fragment_new 265
 #define SSL_F_ssl3_seal_record 266
+#define SSL_F_ssl3_record_sequence_update 267
 #define SSL_R_APP_DATA_IN_HANDSHAKE 100
 #define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 101
 #define SSL_R_BAD_ALERT 102
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index bd3a573..766f8b2 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -990,7 +990,9 @@
   wr->type = type; /* not needed but helps for debugging */
   wr->length += DTLS1_RT_HEADER_LENGTH;
 
-  ssl3_record_sequence_update(&(s->s3->write_sequence[0]));
+  if (!ssl3_record_sequence_update(&s->s3->write_sequence[2], 6)) {
+    goto err;
+  }
 
   /* now let's set up wb */
   wb->left = prefix_len + wr->length;
diff --git a/ssl/s3_enc.c b/ssl/s3_enc.c
index 7bf325a..d6383d7 100644
--- a/ssl/s3_enc.c
+++ b/ssl/s3_enc.c
@@ -415,15 +415,16 @@
   return ret;
 }
 
-void ssl3_record_sequence_update(uint8_t *seq) {
-  int i;
-
-  for (i = 7; i >= 0; i--) {
+int ssl3_record_sequence_update(uint8_t *seq, size_t seq_len) {
+  size_t i;
+  for (i = seq_len - 1; i < seq_len; i--) {
     ++seq[i];
     if (seq[i] != 0) {
-      break;
+      return 1;
     }
   }
+  OPENSSL_PUT_ERROR(SSL, ssl3_record_sequence_update, ERR_R_OVERFLOW);
+  return 0;
 }
 
 int ssl3_alert_code(int code) {
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 4df546d..6278deb 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -787,7 +787,10 @@
 long ssl3_ctx_callback_ctrl(SSL_CTX *s, int cmd, void (*fp)(void));
 int ssl3_pending(const SSL *s);
 
-void ssl3_record_sequence_update(uint8_t *seq);
+/* ssl3_record_sequence_update increments the sequence number in |seq|. It
+ * returns one on success and zero on wraparound. */
+int ssl3_record_sequence_update(uint8_t *seq, size_t seq_len);
+
 int ssl3_do_change_cipher_spec(SSL *ssl);
 
 int ssl3_set_handshake_header(SSL *s, int htype, unsigned long len);
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 6e1cf3a..1f16269 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -597,13 +597,9 @@
     memcpy(p, &seq[2], 6);
     memcpy(ad, dtlsseq, 8);
   } else {
-    int i;
     memcpy(ad, seq, 8);
-    for (i = 7; i >= 0; i--) {
-      ++seq[i];
-      if (seq[i] != 0) {
-        break;
-      }
+    if (!ssl3_record_sequence_update(seq, 8)) {
+      return 0;
     }
   }