1 /* $OpenBSD: cipher_list.c,v 1.3 2015/07/01 07:21:10 bcook Exp $ */ 2 /* 3 * Copyright (c) 2015 Doug Hogan <doug@openbsd.org> 4 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Test TLS ssl bytes (aka cipher suites) to cipher list and back. 21 * 22 * TLSv1.0 - RFC 2246 section 7.4.1.2 (ClientHello struct) 23 * TLSv1.1 - RFC 4346 section 7.4.1.2 (ClientHello struct) 24 * TLSv1.2 - RFC 5246 section 7.4.1.2 (ClientHello struct) 25 * 26 * In all of these standards, the relevant structures are: 27 * 28 * uint8 CipherSuite[2]; 29 * 30 * struct { 31 * ... 32 * CipherSuite cipher_suites<2..2^16-2> 33 * ... 34 * } ClientHello; 35 */ 36 37 #include <openssl/ssl.h> 38 39 #include <stdio.h> 40 #include <string.h> 41 42 #include "tests.h" 43 44 static uint8_t cipher_bytes[] = { 45 0xcc, 0x14, /* ECDHE-ECDSA-CHACHA20-POLY1305 */ 46 0xcc, 0x13, /* ECDHE-RSA-CHACHA20-POLY1305 */ 47 0xcc, 0x15, /* DHE-RSA-CHACHA20-POLY1305 */ 48 0x00, 0x9c, /* AES128-GCM-SHA256 */ 49 0x00, 0x3d, /* AES256-SHA256 */ 50 0x00, 0x09, /* DES-CBC-SHA */ 51 }; 52 53 static uint16_t cipher_values[] = { 54 0xcc14, /* ECDHE-ECDSA-CHACHA20-POLY1305 */ 55 0xcc13, /* ECDHE-RSA-CHACHA20-POLY1305 */ 56 0xcc15, /* DHE-RSA-CHACHA20-POLY1305 */ 57 0x009c, /* AES128-GCM-SHA256 */ 58 0x003d, /* AES256-SHA256 */ 59 0x0009, /* DES-CBC-SHA */ 60 }; 61 62 #define N_CIPHERS (sizeof(cipher_bytes) / 2) 63 64 extern STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, 65 const unsigned char *p, int num); 66 extern int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, 67 unsigned char *p); 68 69 static int 70 ssl_bytes_to_list_alloc(SSL *s, STACK_OF(SSL_CIPHER) **ciphers) 71 { 72 SSL_CIPHER *cipher; 73 uint16_t value; 74 int i; 75 76 *ciphers = ssl_bytes_to_cipher_list(s, cipher_bytes, 77 sizeof(cipher_bytes)); 78 CHECK(*ciphers != NULL); 79 CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS); 80 for (i = 0; i < sk_SSL_CIPHER_num(*ciphers); i++) { 81 cipher = sk_SSL_CIPHER_value(*ciphers, i); 82 CHECK(cipher != NULL); 83 value = SSL_CIPHER_get_value(cipher); 84 CHECK(value == cipher_values[i]); 85 } 86 87 return 1; 88 } 89 90 static int 91 ssl_list_to_bytes_scsv(SSL *s, STACK_OF(SSL_CIPHER) **ciphers) 92 { 93 unsigned char *buf = NULL; 94 size_t buflen; 95 int len; 96 int ret = 0; 97 98 /* Space for cipher bytes, plus reneg SCSV and two spare bytes. */ 99 CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS); 100 buflen = sizeof(cipher_bytes) + 2 + 2; 101 CHECK((buf = calloc(1, buflen)) != NULL); 102 103 len = ssl_cipher_list_to_bytes(s, *ciphers, buf); 104 CHECK_GOTO(len > 0 && (size_t)len == buflen - 2); 105 CHECK_GOTO(memcmp(buf, cipher_bytes, sizeof(cipher_bytes)) == 0); 106 CHECK_GOTO(buf[buflen - 4] == 0x00 && buf[buflen - 3] == 0xff); 107 CHECK_GOTO(buf[buflen - 2] == 0x00 && buf[buflen - 1] == 0x00); 108 109 ret = 1; 110 111 err: 112 free(buf); 113 return ret; 114 } 115 116 static int 117 ssl_list_to_bytes_no_scsv(SSL *s, STACK_OF(SSL_CIPHER) **ciphers) 118 { 119 unsigned char *buf = NULL; 120 size_t buflen; 121 int len; 122 int ret = 0; 123 124 /* Space for cipher bytes and two spare bytes */ 125 CHECK(sk_SSL_CIPHER_num(*ciphers) == N_CIPHERS); 126 buflen = sizeof(cipher_bytes) + 2; 127 CHECK((buf = calloc(1, buflen)) != NULL); 128 buf[buflen - 2] = 0xfe; 129 buf[buflen - 1] = 0xab; 130 131 /* Set renegotiate so it doesn't add SCSV */ 132 s->renegotiate = 1; 133 134 len = ssl_cipher_list_to_bytes(s, *ciphers, buf); 135 CHECK_GOTO(len > 0 && (size_t)len == buflen - 2); 136 CHECK_GOTO(memcmp(buf, cipher_bytes, sizeof(cipher_bytes)) == 0); 137 CHECK_GOTO(buf[buflen - 2] == 0xfe && buf[buflen - 1] == 0xab); 138 139 ret = 1; 140 141 err: 142 free(buf); 143 return ret; 144 } 145 146 static int 147 ssl_bytes_to_list_invalid(SSL *s, STACK_OF(SSL_CIPHER) **ciphers) 148 { 149 uint8_t empty_cipher_bytes[] = {0}; 150 151 sk_SSL_CIPHER_free(*ciphers); 152 153 /* Invalid length: CipherSuite is 2 bytes so it must be even */ 154 *ciphers = ssl_bytes_to_cipher_list(s, cipher_bytes, 155 sizeof(cipher_bytes) - 1); 156 CHECK(*ciphers == NULL); 157 158 /* Invalid length: cipher_suites must be at least 2 */ 159 *ciphers = ssl_bytes_to_cipher_list(s, empty_cipher_bytes, 160 sizeof(empty_cipher_bytes)); 161 CHECK(*ciphers == NULL); 162 163 /* Invalid length: cipher_suites must be at most 2^16-2 */ 164 *ciphers = ssl_bytes_to_cipher_list(s, cipher_bytes, 0x10000); 165 CHECK(*ciphers == NULL); 166 167 /* Invalid len: prototype is signed, but it shouldn't accept len < 0 */ 168 *ciphers = ssl_bytes_to_cipher_list(s, cipher_bytes, -2); 169 CHECK(*ciphers == NULL); 170 171 return 1; 172 } 173 174 int 175 main(void) 176 { 177 STACK_OF(SSL_CIPHER) *ciphers = NULL; 178 SSL_CTX *ctx = NULL; 179 SSL *s = NULL; 180 int rv = 1; 181 182 SSL_library_init(); 183 184 /* Use TLSv1.2 client to get all ciphers. */ 185 CHECK_GOTO((ctx = SSL_CTX_new(TLSv1_2_client_method())) != NULL); 186 CHECK_GOTO((s = SSL_new(ctx)) != NULL); 187 188 if (!ssl_bytes_to_list_alloc(s, &ciphers)) 189 goto err; 190 if (!ssl_list_to_bytes_scsv(s, &ciphers)) 191 goto err; 192 if (!ssl_list_to_bytes_no_scsv(s, &ciphers)) 193 goto err; 194 if (!ssl_bytes_to_list_invalid(s, &ciphers)) 195 goto err; 196 197 rv = 0; 198 199 err: 200 sk_SSL_CIPHER_free(ciphers); 201 SSL_CTX_free(ctx); 202 SSL_free(s); 203 204 if (!rv) 205 printf("PASS %s\n", __FILE__); 206 return rv; 207 } 208