Fix magic SSL reason codes.

SSL reason codes corresponding to alerts have special values. Teach
make_errors.go that values above 1000 are reserved (otherwise it will assign
new values in that namespace). Also fix all the existing reason codes which
corresponded to alerts.

Change-Id: Ieabdf8fd59f4802938616934e1d84e659227cf84
Reviewed-on: https://boringssl-review.googlesource.com/1212
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 3ea2c4b..e8398d7 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1615,6 +1615,9 @@
 
 DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
 
+/* make_errors.go reserves error codes above 1000 for manually-assigned
+ * errors. This value must be kept in sync with reservedReasonCode in
+ * make_errors.h */
 #define SSL_AD_REASON_OFFSET		1000 /* offset to get SSL_R_... value from SSL_AD_... */
 
 /* These alert types are for SSLv3 and TLSv1 */
@@ -2360,16 +2363,17 @@
 const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c);
 #endif
 
-/* BEGIN ERROR CODES */
-/* The following lines are auto generated by the script mkerr.pl. Any changes
- * made after this point may be overwritten when the script is next run.
- */
 void ERR_load_SSL_strings(void);
 
 
 #ifdef  __cplusplus
 }
 #endif
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script make_errors.go. Any
+ * changes made after this point may be overwritten when the script is next run.
+ */
 #define SSL_F_SSL_use_PrivateKey_file 100
 #define SSL_F_dtls1_write_app_data_bytes 101
 #define SSL_F_ssl_cipher_process_rulestr 102
@@ -2582,13 +2586,10 @@
 #define SSL_R_READ_TIMEOUT_EXPIRED 129
 #define SSL_R_KRB5_C_GET_CRED 130
 #define SSL_R_NULL_SSL_CTX 131
-#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 132
-#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 133
 #define SSL_R_ERROR_GENERATING_TMP_RSA_KEY 134
 #define SSL_R_SSL3_SESSION_ID_TOO_LONG 135
 #define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 136
 #define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 137
-#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 138
 #define SSL_R_COOKIE_MISMATCH 139
 #define SSL_R_UNINITIALIZED 140
 #define SSL_R_BAD_CHANGE_CIPHER_SPEC 141
@@ -2597,7 +2598,6 @@
 #define SSL_R_NO_CERTIFICATE_ASSIGNED 144
 #define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 145
 #define SSL_R_PEM_NAME_TOO_SHORT 146
-#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 147
 #define SSL_R_PROTOCOL_IS_SHUTDOWN 148
 #define SSL_R_UNABLE_TO_FIND_SSL_METHOD 149
 #define SSL_R_WRONG_MESSAGE_TYPE 150
@@ -2619,7 +2619,6 @@
 #define SSL_R_RECORD_TOO_LARGE 166
 #define SSL_R_BIO_NOT_SET 167
 #define SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES 168
-#define SSL_R_TLSV1_ALERT_DECODE_ERROR 169
 #define SSL_R_UNKNOWN_PKEY_TYPE 170
 #define SSL_R_CIPHER_CODE_WRONG_LENGTH 171
 #define SSL_R_SSL_SESSION_ID_CONFLICT 172
@@ -2643,7 +2642,6 @@
 #define SSL_R_BAD_DH_G_LENGTH 190
 #define SSL_R_BAD_ALERT_RECORD 191
 #define SSL_R_CIPHER_TABLE_SRC_ERROR 192
-#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 193
 #define SSL_R_UNKNOWN_REMOTE_ERROR_TYPE 194
 #define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 195
 #define SSL_R_MESSAGE_TOO_LONG 196
@@ -2665,7 +2663,6 @@
 #define SSL_R_PSK_NO_CLIENT_CB 212
 #define SSL_R_PEM_NAME_BAD_PREFIX 213
 #define SSL_R_BAD_CHECKSUM 214
-#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 215
 #define SSL_R_NO_CIPHER_MATCH 216
 #define SSL_R_MISSING_TMP_DH_KEY 217
 #define SSL_R_UNSUPPORTED_STATUS_TYPE 218
@@ -2681,12 +2678,8 @@
 #define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING 228
 #define SSL_R_GOST_NOT_SUPPORTED 229
 #define SSL_R_KRB5_C_CC_PRINC 230
-#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 231
-#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 232
-#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 233
 #define SSL_R_INVALID_PURPOSE 234
 #define SSL_R_KRB5_C_MK_REQ 235
-#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 236
 #define SSL_R_BAD_SRTP_MKI_VALUE 237
 #define SSL_R_EVP_DIGESTSIGNINIT_FAILED 238
 #define SSL_R_DIGEST_CHECK_FAILED 239
@@ -2701,7 +2694,6 @@
 #define SSL_R_EXCESSIVE_MESSAGE_SIZE 248
 #define SSL_R_INVALID_COMPRESSION_ALGORITHM 249
 #define SSL_R_SHORT_READ 250
-#define SSL_R_TLSV1_ALERT_ACCESS_DENIED 251
 #define SSL_R_CA_DN_LENGTH_MISMATCH 252
 #define SSL_R_BAD_ECC_CERT 253
 #define SSL_R_NON_SSLV2_INITIAL_PACKET 254
@@ -2713,18 +2705,14 @@
 #define SSL_R_NO_RENEGOTIATION 260
 #define SSL_R_NO_COMPRESSION_SPECIFIED 261
 #define SSL_R_WRONG_CERTIFICATE_TYPE 262
-#define SSL_R_TLSV1_UNRECOGNIZED_NAME 263
 #define SSL_R_CHANNEL_ID_SIGNATURE_INVALID 264
 #define SSL_R_READ_BIO_NOT_SET 265
 #define SSL_R_SSL23_DOING_SESSION_ID_REUSE 266
 #define SSL_R_RENEGOTIATE_EXT_TOO_LONG 267
 #define SSL_R_INVALID_CHALLENGE_LENGTH 268
-#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 269
 #define SSL_R_LIBRARY_HAS_NO_CIPHERS 270
 #define SSL_R_WRONG_CURVE 271
 #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 272
-#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 273
-#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 274
 #define SSL_R_ECC_CERT_NOT_FOR_KEY_AGREEMENT 275
 #define SSL_R_MISSING_RSA_CERTIFICATE 276
 #define SSL_R_NO_P256_SUPPORT 277
@@ -2768,12 +2756,10 @@
 #define SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS 316
 #define SSL_R_HTTP_REQUEST 317
 #define SSL_R_KRB5_S_INIT 318
-#define SSL_R_TLSV1_ALERT_USER_CANCELLED 319
 #define SSL_R_RECORD_LENGTH_MISMATCH 320
 #define SSL_R_BAD_LENGTH 321
 #define SSL_R_NO_REQUIRED_DIGEST 322
 #define SSL_R_KRB5 323
-#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 324
 #define SSL_R_CCS_RECEIVED_EARLY 325
 #define SSL_R_MISSING_ECDSA_SIGNING_CERT 326
 #define SSL_R_D2I_ECDSA_SIG 327
@@ -2785,7 +2771,6 @@
 #define SSL_R_UNABLE_TO_FIND_DH_PARAMETERS 333
 #define SSL_R_NO_CERTIFICATE_SET 334
 #define SSL_R_SSL_SESSION_ID_CALLBACK_FAILED 335
-#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 336
 #define SSL_R_NO_CERTIFICATES_RETURNED 337
 #define SSL_R_BAD_WRITE_RETRY 338
 #define SSL_R_BAD_SSL_FILETYPE 339
@@ -2795,7 +2780,6 @@
 #define SSL_R_NO_CIPHERS_PASSED 343
 #define SSL_R_NO_VERIFY_CALLBACK 344
 #define SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE 345
-#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 346
 #define SSL_R_WRONG_NUMBER_OF_KEY_BITS 347
 #define SSL_R_UNEXPECTED_MESSAGE 348
 #define SSL_R_MISSING_DH_DSA_CERT 349
@@ -2813,22 +2797,17 @@
 #define SSL_R_PSK_IDENTITY_NOT_FOUND 361
 #define SSL_R_UNKNOWN_ALERT_TYPE 362
 #define SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER 363
-#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 364
 #define SSL_R_BAD_AUTHENTICATION_TYPE 365
 #define SSL_R_DECRYPTION_FAILED 366
 #define SSL_R_WRONG_SSL_VERSION 367
 #define SSL_R_NO_CERTIFICATE_RETURNED 368
-#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 369
 #define SSL_R_CA_DN_TOO_LONG 370
 #define SSL_R_GOT_A_FIN_BEFORE_A_CCS 371
 #define SSL_R_COMPRESSION_LIBRARY_ERROR 372
-#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 373
 #define SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS 374
 #define SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED 375
 #define SSL_R_BAD_ECPOINT 376
 #define SSL_R_BAD_HANDSHAKE_LENGTH 377
-#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 378
-#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 379
 #define SSL_R_KRB5_S_RD_REQ 380
 #define SSL_R_PEER_ERROR_NO_CERTIFICATE 381
 #define SSL_R_PRE_MAC_LENGTH_TOO_LONG 382
@@ -2849,7 +2828,6 @@
 #define SSL_R_EXTRA_DATA_IN_MESSAGE 397
 #define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 398
 #define SSL_R_CONNECTION_ID_IS_DIFFERENT 399
-#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 400
 #define SSL_R_MISSING_VERIFY_MESSAGE 402
 #define SSL_R_BAD_DSA_SIGNATURE 403
 #define SSL_R_UNKNOWN_SSL_VERSION 404
@@ -2862,12 +2840,10 @@
 #define SSL_R_RECORD_TOO_SMALL 411
 #define SSL_R_ENCRYPTED_LENGTH_TOO_LONG 412
 #define SSL_R_UNSUPPORTED_SSL_VERSION 413
-#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 414
 #define SSL_R_UNABLE_TO_EXTRACT_PUBLIC_KEY 415
 #define SSL_R_MISSING_EXPORT_TMP_RSA_KEY 416
 #define SSL_R_BAD_DATA 417
 #define SSL_R_KRB5_S_TKT_NYV 418
-#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 419
 #define SSL_R_BAD_PROTOCOL_VERSION_NUMBER 420
 #define SSL_R_BAD_MESSAGE_TYPE 421
 #define SSL_R_MISSING_ECDH_CERT 422
@@ -2888,5 +2864,33 @@
 #define SSL_R_CLIENTHELLO_PARSE_FAILED 437
 #define SSL_R_CONNECTION_REJECTED 438
 #define SSL_R_DECODE_ERROR 439
+#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
+#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
+#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021
+#define SSL_R_TLSV1_ALERT_RECORD_OVERFLOW 1022
+#define SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE 1030
+#define SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE 1040
+#define SSL_R_SSLV3_ALERT_NO_CERTIFICATE 1041
+#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042
+#define SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE 1043
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED 1044
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED 1045
+#define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN 1046
+#define SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER 1047
+#define SSL_R_TLSV1_ALERT_UNKNOWN_CA 1048
+#define SSL_R_TLSV1_ALERT_ACCESS_DENIED 1049
+#define SSL_R_TLSV1_ALERT_DECODE_ERROR 1050
+#define SSL_R_TLSV1_ALERT_DECRYPT_ERROR 1051
+#define SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION 1060
+#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070
+#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071
+#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080
+#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
+#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100
+#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110
+#define SSL_R_TLSV1_CERTIFICATE_UNOBTAINABLE 1111
+#define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
+#define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113
+#define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114
 
 #endif
diff --git a/ssl/CMakeLists.txt b/ssl/CMakeLists.txt
index 3e613b4..bbbc1aa 100644
--- a/ssl/CMakeLists.txt
+++ b/ssl/CMakeLists.txt
@@ -44,3 +44,11 @@
 
 	$<TARGET_OBJECTS:pqueue>
 )
+
+add_executable(
+	ssl_test
+
+	ssl_test.c
+)
+
+target_link_libraries(ssl_test crypto)
diff --git a/ssl/ssl_error.c b/ssl/ssl_error.c
index 51754d0..0097d60 100644
--- a/ssl/ssl_error.c
+++ b/ssl/ssl_error.c
@@ -117,7 +117,6 @@
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_client_hello, 0), "ssl3_get_client_hello"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_client_key_exchange, 0), "ssl3_get_client_key_exchange"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_finished, 0), "ssl3_get_finished"},
-  {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_key_exchange, 0), "ssl3_get_server_key_exchange"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_message, 0), "ssl3_get_message"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_new_session_ticket, 0), "ssl3_get_new_session_ticket"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_next_proto, 0), "ssl3_get_next_proto"},
@@ -125,6 +124,7 @@
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_certificate, 0), "ssl3_get_server_certificate"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_done, 0), "ssl3_get_server_done"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_hello, 0), "ssl3_get_server_hello"},
+  {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_get_server_key_exchange, 0), "ssl3_get_server_key_exchange"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_handshake_mac, 0), "ssl3_handshake_mac"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_read_bytes, 0), "ssl3_read_bytes"},
   {ERR_PACK(ERR_LIB_SSL, SSL_F_ssl3_read_n, 0), "ssl3_read_n"},
diff --git a/ssl/ssl_test.c b/ssl/ssl_test.c
new file mode 100644
index 0000000..4652e85
--- /dev/null
+++ b/ssl/ssl_test.c
@@ -0,0 +1,30 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+
+#include "openssl/ssl.h"
+
+int main() {
+  /* Some error codes are special, but the make_errors.go script doesn't know
+   * this. This test will catch the case where something regenerates the error
+   * codes with the script but doesn't fix up the special ones. */
+  if (SSL_R_TLSV1_ALERT_NO_RENEGOTIATION != 100 + SSL_AD_REASON_OFFSET) {
+    fprintf(stderr, "SSL alert errors don't match up.\n");
+    return 1;
+  }
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/util/all_tests.sh b/util/all_tests.sh
index 5bfad27..def97ff 100644
--- a/util/all_tests.sh
+++ b/util/all_tests.sh
@@ -37,6 +37,7 @@
 ./crypto/x509v3/tab_test
 ./crypto/x509v3/v3name_test
 ./crypto/bytestring/bytestring_test
+./ssl/ssl_test
 "
 
 IFS=$'\n'
diff --git a/util/make_errors.go b/util/make_errors.go
index 20b3e2d..f770e3d 100644
--- a/util/make_errors.go
+++ b/util/make_errors.go
@@ -28,6 +28,11 @@
 	"unicode"
 )
 
+// ssl.h reserves values 1000 and above for error codes corresponding to
+// alerts. If automatically assigned reason codes exceed this value, this script
+// will error. This must be kept in sync with SSL_AD_REASON_OFFSET in ssl.h.
+const reservedReasonCode = 1000
+
 var resetFlag *bool = flag.Bool("reset", false, "If true, ignore current assignments and reassign from scratch")
 
 func makeErrors(reset bool) error {
@@ -59,7 +64,14 @@
 	if reset {
 		err = nil
 		functions = make(map[string]int)
-		reasons = make(map[string]int)
+		// Retain any reason codes above reservedReasonCode.
+		newReasons := make(map[string]int)
+		for key, value := range reasons {
+			if value >= reservedReasonCode {
+				newReasons[key] = value
+			}
+		}
+		reasons = newReasons
 	}
 
 	if err != nil {
@@ -87,8 +99,8 @@
 		}
 	}
 
-	assignNewValues(functions)
-	assignNewValues(reasons)
+	assignNewValues(functions, -1)
+	assignNewValues(reasons, reservedReasonCode)
 
 	headerFile, err = os.Open(headerPath)
 	if err != nil {
@@ -294,10 +306,13 @@
 	}
 }
 
-func assignNewValues(assignments map[string]int) {
+func assignNewValues(assignments map[string]int, reserved int) {
 	max := 99
 
 	for _, value := range assignments {
+		if reserved >= 0 && value >= reserved {
+			continue
+		}
 		if value > max {
 			max = value
 		}
@@ -307,6 +322,11 @@
 
 	for key, value := range assignments {
 		if value == -1 {
+			if reserved >= 0 && max >= reserved {
+				// If this happens, try passing
+				// -reset. Otherwise bump up reservedReasonCode.
+				panic("Automatically-assigned values exceeded limit!")
+			}
 			assignments[key] = max
 			max++
 		}