1 /* $OpenBSD: asn1test.c,v 1.3 2014/12/07 20:00:13 bcook Exp $ */ 2 /* 3 * Copyright (c) 2014 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <err.h> 19 #include <stdlib.h> 20 21 #include <openssl/bio.h> 22 #include <openssl/err.h> 23 #include <openssl/ssl.h> 24 #include <openssl/tls1.h> 25 26 int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); 27 SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, 28 long length); 29 30 struct ssl_asn1_test { 31 SSL_SESSION session; 32 const unsigned char asn1[512]; 33 int asn1_len; 34 }; 35 36 unsigned char tlsext_tick[] = { 37 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 38 0x2d, 0x30, 0x31, 0x36, 0x30, 0x3a, 0x20, 0x37, 39 0x74, 0x68, 0x20, 0x41, 0x70, 0x72, 0x69, 0x6c, 40 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 41 0x45, 0x2d, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x35, 42 0x32, 0x39, 0x38, 0x3a, 0x20, 0x38, 0x74, 0x68, 43 0x20, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, 44 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 45 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 0x39, 46 0x38, 0x3a, 0x20, 0x32, 0x31, 0x73, 0x74, 0x20, 47 0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, 48 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 49 0x30, 0x31, 0x34, 0x2d, 0x33, 0x34, 0x37, 0x30, 50 0x3a, 0x20, 0x33, 0x30, 0x74, 0x68, 0x20, 0x4d, 51 0x61, 0x79, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 52 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 53 0x2d, 0x30, 0x31, 0x39, 0x35, 0x3a, 0x20, 0x35, 54 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 55 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 56 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x32, 57 0x32, 0x31, 0x3a, 0x20, 0x35, 0x74, 0x68, 0x20, 58 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x31, 59 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 60 0x31, 0x34, 0x2d, 0x30, 0x32, 0x32, 0x34, 0x3a, 61 0x20, 0x35, 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e, 62 0x65, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 63 }; 64 65 struct ssl_asn1_test ssl_asn1_tests[] = { 66 { 67 { 68 .cipher_id = 0x03000000L | 1, 69 .ssl_version = TLS1_2_VERSION, 70 }, 71 { 72 0x30, 0x13, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03, 73 0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 0x00, 0x04, 74 0x00, 0xa4, 0x02, 0x04, 0x00, 75 }, 76 21, 77 }, 78 { 79 { 80 .cipher_id = 0x03000000L | 1, 81 .ssl_version = TLS1_2_VERSION, 82 .master_key_length = 26, 83 .session_id = "0123456789", 84 .session_id_length = 10, 85 .sid_ctx = "abcdefghijklmnopqrstuvwxyz", 86 .sid_ctx_length = 26, 87 }, 88 { 89 0x30, 0x51, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03, 90 0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 0x0a, 0x30, 91 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 92 0x39, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 95 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x1c, 0x04, 96 0x1a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 97 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 98 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 99 0x78, 0x79, 0x7a, 100 }, 101 83, 102 }, 103 { 104 { 105 .cipher_id = 0x03000000L | 1, 106 .ssl_version = TLS1_2_VERSION, 107 .master_key_length = 26, 108 .session_id = "0123456789", 109 .session_id_length = 10, 110 .sid_ctx = "abcdefghijklmnopqrstuvwxyz", 111 .sid_ctx_length = 26, 112 .time = 1405266069, 113 .timeout = 5, 114 .verify_result = 42, 115 .tlsext_hostname = "libressl.openbsd.org", 116 .tlsext_tick_lifetime_hint = 0x7abbccdd, 117 .tlsext_tick = tlsext_tick, 118 .tlsext_ticklen = 207, 119 }, 120 { 121 0x30, 0x82, 0x01, 0x58, 0x02, 0x01, 0x01, 0x02, 122 0x02, 0x03, 0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 123 0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 124 0x37, 0x38, 0x39, 0x04, 0x1a, 0x00, 0x00, 0x00, 125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 128 0x06, 0x02, 0x04, 0x53, 0xc2, 0xa8, 0x95, 0xa2, 129 0x03, 0x02, 0x01, 0x05, 0xa4, 0x1c, 0x04, 0x1a, 130 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 131 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 132 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 133 0x79, 0x7a, 0xa5, 0x03, 0x02, 0x01, 0x2a, 0xa6, 134 0x16, 0x04, 0x14, 0x6c, 0x69, 0x62, 0x72, 0x65, 135 0x73, 0x73, 0x6c, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 136 0x62, 0x73, 0x64, 0x2e, 0x6f, 0x72, 0x67, 0xa9, 137 0x06, 0x02, 0x04, 0x7a, 0xbb, 0xcc, 0xdd, 0xaa, 138 0x81, 0xd2, 0x04, 0x81, 0xcf, 0x43, 0x56, 0x45, 139 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 140 0x36, 0x30, 0x3a, 0x20, 0x37, 0x74, 0x68, 0x20, 141 0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, 142 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 143 0x30, 0x31, 0x30, 0x2d, 0x35, 0x32, 0x39, 0x38, 144 0x3a, 0x20, 0x38, 0x74, 0x68, 0x20, 0x41, 0x70, 145 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x34, 146 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 147 0x34, 0x2d, 0x30, 0x31, 0x39, 0x38, 0x3a, 0x20, 148 0x32, 0x31, 0x73, 0x74, 0x20, 0x41, 0x70, 0x72, 149 0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 150 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 151 0x2d, 0x33, 0x34, 0x37, 0x30, 0x3a, 0x20, 0x33, 152 0x30, 0x74, 0x68, 0x20, 0x4d, 0x61, 0x79, 0x20, 153 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 154 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 155 0x39, 0x35, 0x3a, 0x20, 0x35, 0x74, 0x68, 0x20, 156 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x31, 157 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 158 0x31, 0x34, 0x2d, 0x30, 0x32, 0x32, 0x31, 0x3a, 159 0x20, 0x35, 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e, 160 0x65, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 161 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 162 0x30, 0x32, 0x32, 0x34, 0x3a, 0x20, 0x35, 0x74, 163 0x68, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 164 0x30, 0x31, 0x34, 0x0a, 165 }, 166 348, 167 }, 168 }; 169 170 #define N_SSL_ASN1_TESTS \ 171 (sizeof(ssl_asn1_tests) / sizeof(*ssl_asn1_tests)) 172 173 static int 174 session_strcmp(const unsigned char *o1, const unsigned char *o2, size_t len) 175 { 176 if (o1 == NULL && o2 == NULL) 177 return (0); 178 if (o1 == NULL || o2 == NULL) 179 return (1); 180 return memcmp(o1, o2, len); 181 } 182 183 static int 184 session_cmp(SSL_SESSION *s1, SSL_SESSION *s2) 185 { 186 /* Compare two sessions, from the perspective of ASN1. */ 187 if (s1->ssl_version != s2->ssl_version) { 188 fprintf(stderr, "ssl_version differs: %i != %i\n", 189 s1->ssl_version, s2->ssl_version); 190 return (1); 191 } 192 if (s1->cipher_id != s2->cipher_id) { 193 fprintf(stderr, "cipher_id differs: %li != %li\n", 194 s1->cipher_id, s2->cipher_id); 195 return (1); 196 } 197 198 if (s1->master_key_length != s2->master_key_length) { 199 fprintf(stderr, "master_key_length differs: %i != %i\n", 200 s1->master_key_length, s2->master_key_length); 201 return (1); 202 } 203 if (session_strcmp(s1->master_key, s2->master_key, 204 s1->master_key_length) != 0) { 205 fprintf(stderr, "master_key differs\n"); 206 return (1); 207 } 208 209 if (s1->session_id_length != s2->session_id_length) { 210 fprintf(stderr, "session_id_length differs: %i != %i\n", 211 s1->session_id_length, s2->session_id_length); 212 return (1); 213 } 214 if (session_strcmp(s1->session_id, s2->session_id, 215 s1->session_id_length) != 0) { 216 fprintf(stderr, "session_id differs\n"); 217 return (1); 218 } 219 220 if (s1->sid_ctx_length != s2->sid_ctx_length) { 221 fprintf(stderr, "sid_ctx_length differs: %i != %i\n", 222 s1->sid_ctx_length, s2->sid_ctx_length); 223 return (1); 224 } 225 if (session_strcmp(s1->sid_ctx, s2->sid_ctx, 226 s1->sid_ctx_length) != 0) { 227 fprintf(stderr, "sid_ctx differs\n"); 228 return (1); 229 } 230 231 /* d2i_SSL_SESSION uses the current time if decoding a zero value. */ 232 if ((s1->time != s2->time) && s1->time != 0 && s2->time != 0) { 233 fprintf(stderr, "time differs: %lli != %lli\n", 234 (long long)s1->time, (long long)s2->time); 235 return (1); 236 } 237 /* d2i_SSL_SESSION uses a timeout of 3 if decoding a zero value. */ 238 if ((s1->timeout != s2->timeout) && 239 s1->timeout != 3 && s2->timeout != 3) { 240 fprintf(stderr, "timeout differs: %li != %li\n", 241 s1->timeout, s2->timeout); 242 return (1); 243 } 244 245 /* Ensure that a certificate is or is not present in both. */ 246 if ((s1->peer != NULL || s2->peer != NULL) && 247 (s1->peer == NULL || s2->peer == NULL)) { 248 fprintf(stderr, "peer differs\n"); 249 return (1); 250 } 251 252 if (s1->verify_result != s2->verify_result) { 253 fprintf(stderr, "verify_result differs: %li != %li\n", 254 s1->verify_result, s2->verify_result); 255 return (1); 256 } 257 258 if (session_strcmp(s1->tlsext_hostname, s2->tlsext_hostname, 259 (s1->tlsext_hostname ? strlen(s1->tlsext_hostname) : 0)) != 0) { 260 fprintf(stderr, "sid_ctx differs\n"); 261 return (1); 262 } 263 if (s1->tlsext_tick_lifetime_hint != s2->tlsext_tick_lifetime_hint) { 264 fprintf(stderr, "tlsext_tick_lifetime_hint differs: " 265 "%li != %li\n", s1->tlsext_tick_lifetime_hint, 266 s2->tlsext_tick_lifetime_hint); 267 return (1); 268 } 269 if (s1->tlsext_ticklen != s2->tlsext_ticklen) { 270 fprintf(stderr, "tlsext_ticklen differs: %zu != %zu\n", 271 s1->tlsext_ticklen, s2->tlsext_ticklen); 272 return (1); 273 } 274 if (session_strcmp(s1->tlsext_tick, s2->tlsext_tick, 275 s1->tlsext_ticklen) != 0) { 276 fprintf(stderr, "tlsext_tick differs\n"); 277 return (1); 278 } 279 280 return (0); 281 } 282 283 static int 284 do_ssl_asn1_test(int test_no, struct ssl_asn1_test *sat) 285 { 286 SSL_SESSION session, *sp = NULL; 287 unsigned char *ap, *asn1 = NULL; 288 const unsigned char *pp; 289 int i, len, rv = 1; 290 291 len = i2d_SSL_SESSION(&sat->session, NULL); 292 if (len != sat->asn1_len) { 293 fprintf(stderr, "FAIL: test %i returned ASN1 length %i, " 294 "want %i\n", test_no, len, sat->asn1_len); 295 goto failed; 296 } 297 298 if ((asn1 = malloc(len)) == NULL) 299 errx(1, "failed to allocate memory"); 300 301 ap = asn1; 302 len = i2d_SSL_SESSION(&sat->session, &ap); 303 if ((ap - asn1) > len) { 304 fprintf(stderr, "FAIL: test %i overflowed ticket buffer " 305 "(%i > %i)\n", test_no, (int)(ap - asn1), len); 306 goto failed; 307 } 308 309 /* 310 * Length *should* be the same, but check it again since the code 311 * path is different. 312 */ 313 if (len != sat->asn1_len) { 314 fprintf(stderr, "FAIL: test %i returned ASN1 length %i, " 315 "want %i\n", test_no, len, sat->asn1_len); 316 goto failed; 317 } 318 319 if (memcmp(asn1, &sat->asn1, len) != 0) { 320 fprintf(stderr, "FAIL: test %i - encoding differs:\n", test_no); 321 fprintf(stderr, "encoding:\n"); 322 for (i = 1; i <= len; i++) { 323 fprintf(stderr, " 0x%02hhx,", asn1[i - 1]); 324 if (i % 8 == 0) 325 fprintf(stderr, "\n"); 326 } 327 fprintf(stderr, "\n"); 328 fprintf(stderr, "test data:\n"); 329 for (i = 1; i <= sat->asn1_len; i++) { 330 fprintf(stderr, " 0x%02hhx,", sat->asn1[i - 1]); 331 if (i % 8 == 0) 332 fprintf(stderr, "\n"); 333 } 334 fprintf(stderr, "\n"); 335 goto failed; 336 } 337 338 sp = &session; 339 memset(sp, 0, sizeof(*sp)); 340 pp = sat->asn1; 341 342 if ((sp = d2i_SSL_SESSION(&sp, &pp, sat->asn1_len)) == NULL) { 343 fprintf(stderr, "FAIL: test %i - decoding failed\n", test_no); 344 goto failed; 345 } 346 347 if (session_cmp(sp, &sat->session) != 0) { 348 fprintf(stderr, "FAIL: test %i - decoding differs\n", test_no); 349 goto failed; 350 } 351 352 rv = 0; 353 354 failed: 355 ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE)); 356 357 free(asn1); 358 359 return (rv); 360 } 361 362 int 363 main(int argc, char **argv) 364 { 365 int failed = 0; 366 size_t i; 367 368 SSL_library_init(); 369 SSL_load_error_strings(); 370 371 for (i = 0; i < N_SSL_ASN1_TESTS; i++) 372 failed += do_ssl_asn1_test(i, &ssl_asn1_tests[i]); 373 374 return (failed); 375 } 376