1 /* $OpenBSD: asn1test.c,v 1.2 2014/07/16 17:38:19 miod 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 .sid_ctx = "abcdefghijklmnopqrstuvwxyz", 83 .master_key_length = 26, 84 .session_id = "0123456789", 85 .session_id_length = 10, 86 .sid_ctx = "abcdefghijklmnopqrstuvwxyz", 87 .sid_ctx_length = 26, 88 }, 89 { 90 0x30, 0x51, 0x02, 0x01, 0x01, 0x02, 0x02, 0x03, 91 0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 0x0a, 0x30, 92 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 93 0x39, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 96 0x00, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x1c, 0x04, 97 0x1a, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 98 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 99 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 100 0x78, 0x79, 0x7a, 101 }, 102 83, 103 }, 104 { 105 { 106 .cipher_id = 0x03000000L | 1, 107 .ssl_version = TLS1_2_VERSION, 108 .sid_ctx = "abcdefghijklmnopqrstuvwxyz", 109 .master_key_length = 26, 110 .session_id = "0123456789", 111 .session_id_length = 10, 112 .sid_ctx = "abcdefghijklmnopqrstuvwxyz", 113 .sid_ctx_length = 26, 114 .time = 1405266069, 115 .timeout = 5, 116 .verify_result = 42, 117 .tlsext_hostname = "libressl.openbsd.org", 118 .tlsext_tick_lifetime_hint = 0x7abbccdd, 119 .tlsext_tick = tlsext_tick, 120 .tlsext_ticklen = 207, 121 }, 122 { 123 0x30, 0x82, 0x01, 0x58, 0x02, 0x01, 0x01, 0x02, 124 0x02, 0x03, 0x03, 0x04, 0x02, 0x00, 0x01, 0x04, 125 0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 126 0x37, 0x38, 0x39, 0x04, 0x1a, 0x00, 0x00, 0x00, 127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 130 0x06, 0x02, 0x04, 0x53, 0xc2, 0xa8, 0x95, 0xa2, 131 0x03, 0x02, 0x01, 0x05, 0xa4, 0x1c, 0x04, 0x1a, 132 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 133 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 134 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 135 0x79, 0x7a, 0xa5, 0x03, 0x02, 0x01, 0x2a, 0xa6, 136 0x16, 0x04, 0x14, 0x6c, 0x69, 0x62, 0x72, 0x65, 137 0x73, 0x73, 0x6c, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 138 0x62, 0x73, 0x64, 0x2e, 0x6f, 0x72, 0x67, 0xa9, 139 0x06, 0x02, 0x04, 0x7a, 0xbb, 0xcc, 0xdd, 0xaa, 140 0x81, 0xd2, 0x04, 0x81, 0xcf, 0x43, 0x56, 0x45, 141 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 142 0x36, 0x30, 0x3a, 0x20, 0x37, 0x74, 0x68, 0x20, 143 0x41, 0x70, 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, 144 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 145 0x30, 0x31, 0x30, 0x2d, 0x35, 0x32, 0x39, 0x38, 146 0x3a, 0x20, 0x38, 0x74, 0x68, 0x20, 0x41, 0x70, 147 0x72, 0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x34, 148 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 149 0x34, 0x2d, 0x30, 0x31, 0x39, 0x38, 0x3a, 0x20, 150 0x32, 0x31, 0x73, 0x74, 0x20, 0x41, 0x70, 0x72, 151 0x69, 0x6c, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 152 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 153 0x2d, 0x33, 0x34, 0x37, 0x30, 0x3a, 0x20, 0x33, 154 0x30, 0x74, 0x68, 0x20, 0x4d, 0x61, 0x79, 0x20, 155 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 0x56, 0x45, 156 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 0x30, 0x31, 157 0x39, 0x35, 0x3a, 0x20, 0x35, 0x74, 0x68, 0x20, 158 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 0x30, 0x31, 159 0x34, 0x0a, 0x43, 0x56, 0x45, 0x2d, 0x32, 0x30, 160 0x31, 0x34, 0x2d, 0x30, 0x32, 0x32, 0x31, 0x3a, 161 0x20, 0x35, 0x74, 0x68, 0x20, 0x4a, 0x75, 0x6e, 162 0x65, 0x20, 0x32, 0x30, 0x31, 0x34, 0x0a, 0x43, 163 0x56, 0x45, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x2d, 164 0x30, 0x32, 0x32, 0x34, 0x3a, 0x20, 0x35, 0x74, 165 0x68, 0x20, 0x4a, 0x75, 0x6e, 0x65, 0x20, 0x32, 166 0x30, 0x31, 0x34, 0x0a, 167 }, 168 348, 169 }, 170 }; 171 172 #define N_SSL_ASN1_TESTS \ 173 (sizeof(ssl_asn1_tests) / sizeof(*ssl_asn1_tests)) 174 175 static int 176 session_strcmp(const unsigned char *o1, const unsigned char *o2, size_t len) 177 { 178 if (o1 == NULL && o2 == NULL) 179 return (0); 180 if (o1 == NULL || o2 == NULL) 181 return (1); 182 return memcmp(o1, o2, len); 183 } 184 185 static int 186 session_cmp(SSL_SESSION *s1, SSL_SESSION *s2) 187 { 188 /* Compare two sessions, from the perspective of ASN1. */ 189 if (s1->ssl_version != s2->ssl_version) { 190 fprintf(stderr, "ssl_version differs: %i != %i\n", 191 s1->ssl_version, s2->ssl_version); 192 return (1); 193 } 194 if (s1->cipher_id != s2->cipher_id) { 195 fprintf(stderr, "cipher_id differs: %li != %li\n", 196 s1->cipher_id, s2->cipher_id); 197 return (1); 198 } 199 200 if (s1->master_key_length != s2->master_key_length) { 201 fprintf(stderr, "master_key_length differs: %i != %i\n", 202 s1->master_key_length, s2->master_key_length); 203 return (1); 204 } 205 if (session_strcmp(s1->master_key, s2->master_key, 206 s1->master_key_length) != 0) { 207 fprintf(stderr, "master_key differs\n"); 208 return (1); 209 } 210 211 if (s1->session_id_length != s2->session_id_length) { 212 fprintf(stderr, "session_id_length differs: %i != %i\n", 213 s1->session_id_length, s2->session_id_length); 214 return (1); 215 } 216 if (session_strcmp(s1->session_id, s2->session_id, 217 s1->session_id_length) != 0) { 218 fprintf(stderr, "session_id differs\n"); 219 return (1); 220 } 221 222 if (s1->sid_ctx_length != s2->sid_ctx_length) { 223 fprintf(stderr, "sid_ctx_length differs: %i != %i\n", 224 s1->sid_ctx_length, s2->sid_ctx_length); 225 return (1); 226 } 227 if (session_strcmp(s1->sid_ctx, s2->sid_ctx, 228 s1->sid_ctx_length) != 0) { 229 fprintf(stderr, "sid_ctx differs\n"); 230 return (1); 231 } 232 233 /* d2i_SSL_SESSION uses the current time if decoding a zero value. */ 234 if ((s1->time != s2->time) && s1->time != 0 && s2->time != 0) { 235 fprintf(stderr, "time differs: %lli != %lli\n", 236 (long long)s1->time, (long long)s2->time); 237 return (1); 238 } 239 /* d2i_SSL_SESSION uses a timeout of 3 if decoding a zero value. */ 240 if ((s1->timeout != s2->timeout) && 241 s1->timeout != 3 && s2->timeout != 3) { 242 fprintf(stderr, "timeout differs: %li != %li\n", 243 s1->timeout, s2->timeout); 244 return (1); 245 } 246 247 /* Ensure that a certificate is or is not present in both. */ 248 if ((s1->peer != NULL || s2->peer != NULL) && 249 (s1->peer == NULL || s2->peer == NULL)) { 250 fprintf(stderr, "peer differs\n"); 251 return (1); 252 } 253 254 if (s1->verify_result != s2->verify_result) { 255 fprintf(stderr, "verify_result differs: %li != %li\n", 256 s1->verify_result, s2->verify_result); 257 return (1); 258 } 259 260 if (session_strcmp(s1->tlsext_hostname, s2->tlsext_hostname, 261 (s1->tlsext_hostname ? strlen(s1->tlsext_hostname) : 0)) != 0) { 262 fprintf(stderr, "sid_ctx differs\n"); 263 return (1); 264 } 265 if (s1->tlsext_tick_lifetime_hint != s2->tlsext_tick_lifetime_hint) { 266 fprintf(stderr, "tlsext_tick_lifetime_hint differs: " 267 "%li != %li\n", s1->tlsext_tick_lifetime_hint, 268 s2->tlsext_tick_lifetime_hint); 269 return (1); 270 } 271 if (s1->tlsext_ticklen != s2->tlsext_ticklen) { 272 fprintf(stderr, "tlsext_ticklen differs: %zu != %zu\n", 273 s1->tlsext_ticklen, s2->tlsext_ticklen); 274 return (1); 275 } 276 if (session_strcmp(s1->tlsext_tick, s2->tlsext_tick, 277 s1->tlsext_ticklen) != 0) { 278 fprintf(stderr, "tlsext_tick differs\n"); 279 return (1); 280 } 281 282 return (0); 283 } 284 285 static int 286 do_ssl_asn1_test(int test_no, struct ssl_asn1_test *sat) 287 { 288 SSL_SESSION session, *sp = NULL; 289 unsigned char *ap, *asn1 = NULL; 290 const unsigned char *pp; 291 int i, len, rv = 1; 292 293 len = i2d_SSL_SESSION(&sat->session, NULL); 294 if (len != sat->asn1_len) { 295 fprintf(stderr, "FAIL: test %i returned ASN1 length %i, " 296 "want %i\n", test_no, len, sat->asn1_len); 297 goto failed; 298 } 299 300 if ((asn1 = malloc(len)) == NULL) 301 errx(1, "failed to allocate memory"); 302 303 ap = asn1; 304 len = i2d_SSL_SESSION(&sat->session, &ap); 305 if ((ap - asn1) > len) { 306 fprintf(stderr, "FAIL: test %i overflowed ticket buffer " 307 "(%i > %i)\n", test_no, (int)(ap - asn1), len); 308 goto failed; 309 } 310 311 /* 312 * Length *should* be the same, but check it again since the code 313 * path is different. 314 */ 315 if (len != sat->asn1_len) { 316 fprintf(stderr, "FAIL: test %i returned ASN1 length %i, " 317 "want %i\n", test_no, len, sat->asn1_len); 318 goto failed; 319 } 320 321 if (memcmp(asn1, &sat->asn1, len) != 0) { 322 fprintf(stderr, "FAIL: test %i - encoding differs:\n", test_no); 323 fprintf(stderr, "encoding:\n"); 324 for (i = 1; i <= len; i++) { 325 fprintf(stderr, " 0x%02hhx,", asn1[i - 1]); 326 if (i % 8 == 0) 327 fprintf(stderr, "\n"); 328 } 329 fprintf(stderr, "\n"); 330 fprintf(stderr, "test data:\n"); 331 for (i = 1; i <= sat->asn1_len; i++) { 332 fprintf(stderr, " 0x%02hhx,", sat->asn1[i - 1]); 333 if (i % 8 == 0) 334 fprintf(stderr, "\n"); 335 } 336 fprintf(stderr, "\n"); 337 goto failed; 338 } 339 340 sp = &session; 341 memset(sp, 0, sizeof(*sp)); 342 pp = sat->asn1; 343 344 if ((sp = d2i_SSL_SESSION(&sp, &pp, sat->asn1_len)) == NULL) { 345 fprintf(stderr, "FAIL: test %i - decoding failed\n", test_no); 346 goto failed; 347 } 348 349 if (session_cmp(sp, &sat->session) != 0) { 350 fprintf(stderr, "FAIL: test %i - decoding differs\n", test_no); 351 goto failed; 352 } 353 354 rv = 0; 355 356 failed: 357 ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE)); 358 359 free(asn1); 360 361 return (rv); 362 } 363 364 int 365 main(int argc, char **argv) 366 { 367 int failed = 0; 368 size_t i; 369 370 SSL_library_init(); 371 SSL_load_error_strings(); 372 373 for (i = 0; i < N_SSL_ASN1_TESTS; i++) 374 failed += do_ssl_asn1_test(i, &ssl_asn1_tests[i]); 375 376 return (failed); 377 } 378