1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (c) 2014, Google Inc. 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Permission to use, copy, modify, and/or distribute this software for any 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * purpose with or without fee is hereby granted, provided that the above 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copyright notice and this permission notice appear in all copies. 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdio.h> 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h> 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 18e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <string> 19e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <vector> 20e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/base64.h> 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bio.h> 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ssl.h> 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 26e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "test/scoped_types.h" 27e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 28e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystruct ExpectedCipher { 29e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley unsigned long id; 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int in_group_flag; 31e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}; 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 33e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystruct CipherTest { 34e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // The rule string to apply. 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const char *rule; 36e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // The list of expected ciphers, in order, terminated with -1. 37e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley const ExpectedCipher *expected; 38e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}; 39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 40e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// Selecting individual ciphers should work. 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kRule1[] = 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-ECDSA-CHACHA20-POLY1305:" 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-RSA-CHACHA20-POLY1305:" 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-ECDSA-AES128-GCM-SHA256:" 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-RSA-AES128-GCM-SHA256"; 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 47e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ExpectedCipher kExpected1[] = { 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 }, 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 }, 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 }, 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 }, 52e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { 0, 0 }, 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 55e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// + reorders selected ciphers to the end, keeping their relative 56e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// order. 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kRule2[] = 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-ECDSA-CHACHA20-POLY1305:" 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-RSA-CHACHA20-POLY1305:" 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-ECDSA-AES128-GCM-SHA256:" 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-RSA-AES128-GCM-SHA256:" 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "+aRSA"; 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 64e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ExpectedCipher kExpected2[] = { 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 }, 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 }, 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 }, 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 }, 69e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { 0, 0 }, 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 72e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// ! banishes ciphers from future selections. 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kRule3[] = 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "!aRSA:" 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-ECDSA-CHACHA20-POLY1305:" 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-RSA-CHACHA20-POLY1305:" 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-ECDSA-AES128-GCM-SHA256:" 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-RSA-AES128-GCM-SHA256"; 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 80e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ExpectedCipher kExpected3[] = { 81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 }, 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 }, 83e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { 0, 0 }, 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 86e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// Multiple masks can be ANDed in a single rule. 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kRule4[] = "kRSA+AESGCM+AES128"; 88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 89e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ExpectedCipher kExpected4[] = { 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 }, 91e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { 0, 0 }, 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 94e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// - removes selected ciphers, but preserves their order for future 95e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// selections. Select AES_128_GCM, but order the key exchanges RSA, 96e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// DHE_RSA, ECDHE_RSA. 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kRule5[] = 98e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "ALL:-kECDHE:-kDHE:-kRSA:-ALL:" 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "AESGCM+AES128+aRSA"; 100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 101e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ExpectedCipher kExpected5[] = { 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 }, 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0 }, 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 }, 105e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { 0, 0 }, 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 108e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// Unknown selectors are no-ops. 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kRule6[] = 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-ECDSA-CHACHA20-POLY1305:" 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-RSA-CHACHA20-POLY1305:" 112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-ECDSA-AES128-GCM-SHA256:" 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-RSA-AES128-GCM-SHA256:" 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4"; 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 116e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ExpectedCipher kExpected6[] = { 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 }, 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 }, 119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 }, 120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 }, 121e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { 0, 0 }, 122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 124e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// Square brackets specify equi-preference groups. 125d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kRule7[] = 126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:" 127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "[ECDHE-RSA-CHACHA20-POLY1305]:" 128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ECDHE-RSA-AES128-GCM-SHA256"; 129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 130e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ExpectedCipher kExpected7[] = { 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 1 }, 132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 }, 133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 }, 134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 }, 135e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { 0, 0 }, 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 138e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// @STRENGTH performs a stable strength-sort of the selected 139e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// ciphers and only the selected ciphers. 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kRule8[] = 141e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // To simplify things, banish all but {ECDHE_RSA,RSA} x 142e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1. 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:" 144e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Order some ciphers backwards by strength. 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:" 146e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Select ECDHE ones and sort them by strength. Ties should resolve 147e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // based on the order above. 148e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "kECDHE:@STRENGTH:-ALL:" 149e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Now bring back everything uses RSA. ECDHE_RSA should be first, 150e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // sorted by strength. Then RSA, backwards by strength. 151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "aRSA"; 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 153e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ExpectedCipher kExpected8[] = { 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0 }, 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 }, 156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0 }, 157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0 }, 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { SSL3_CK_RSA_RC4_128_SHA, 0 }, 159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_RSA_WITH_AES_128_SHA, 0 }, 160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { TLS1_CK_RSA_WITH_AES_256_SHA, 0 }, 161e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { 0, 0 }, 162e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}; 163e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 164e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// Exact ciphers may not be used in multi-part rules; they are treated 165e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// as unknown aliases. 166e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const char kRule9[] = 167e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "ECDHE-ECDSA-CHACHA20-POLY1305:" 168e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "ECDHE-RSA-CHACHA20-POLY1305:" 169e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "!ECDHE-RSA-CHACHA20-POLY1305+RSA:" 170e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "!ECDSA+ECDHE-ECDSA-CHACHA20-POLY1305"; 171e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 172e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const ExpectedCipher kExpected9[] = { 173e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 }, 174e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 }, 175e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { 0, 0 }, 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 178e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic CipherTest kCipherTests[] = { 179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { kRule1, kExpected1 }, 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { kRule2, kExpected2 }, 181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { kRule3, kExpected3 }, 182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { kRule4, kExpected4 }, 183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { kRule5, kExpected5 }, 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { kRule6, kExpected6 }, 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { kRule7, kExpected7 }, 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { kRule8, kExpected8 }, 187e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { kRule9, kExpected9 }, 188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley { NULL, NULL }, 189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 191d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char *kBadRules[] = { 192e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Invalid brackets. 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256", 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "RSA]", 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "[[RSA]]", 196e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Operators inside brackets. 197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "[+RSA]", 198e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Unknown directive. 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "@BOGUS", 200e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Empty cipher lists error at SSL_CTX_set_cipher_list. 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "", 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "BOGUS", 203e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // COMPLEMENTOFDEFAULT is empty. 204e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "COMPLEMENTOFDEFAULT", 205e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Invalid command. 206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "?BAR", 207e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Special operators are not allowed if groups are used. 208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:+FOO", 209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO", 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO", 211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH", 212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley NULL, 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}; 214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 215e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic void PrintCipherPreferenceList(ssl_cipher_preference_list_st *list) { 216e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley bool in_group = false; 217e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (size_t i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) { 218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(list->ciphers, i); 219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!in_group && list->in_group_flags[i]) { 220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "\t[\n"); 221e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley in_group = true; 222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "\t"); 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in_group) { 225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, " "); 226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "%s\n", SSL_CIPHER_get_name(cipher)); 228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (in_group && !list->in_group_flags[i]) { 229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "\t]\n"); 230e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley in_group = false; 231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 235e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestCipherRule(CipherTest *t) { 236e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method())); 237e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!ctx) { 238e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 239e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 241e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!SSL_CTX_set_cipher_list(ctx.get(), t->rule)) { 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Error testing cipher rule '%s'\n", t->rule); 243e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 246e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Compare the two lists. 247e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t i; 248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley for (i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) { 249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const SSL_CIPHER *cipher = 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i); 251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (t->expected[i].id != SSL_CIPHER_get_id(cipher) || 252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley t->expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) { 253e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t->rule); 254e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley PrintCipherPreferenceList(ctx->cipher_list); 255e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 259e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (t->expected[i].id != 0) { 260e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t->rule); 261e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley PrintCipherPreferenceList(ctx->cipher_list); 262e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 265e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 268e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestCipherRules() { 269e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (size_t i = 0; kCipherTests[i].rule != NULL; i++) { 270e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!TestCipherRule(&kCipherTests[i])) { 271e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 275e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (size_t i = 0; kBadRules[i] != NULL; i++) { 276e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method())); 277e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!ctx) { 278e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 279e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 280e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (SSL_CTX_set_cipher_list(ctx.get(), kBadRules[i])) { 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", kBadRules[i]); 282e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ERR_clear_error(); 285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 287e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 290e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// kOpenSSLSession is a serialized SSL_SESSION generated from openssl 291e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// s_client -sess_out. 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kOpenSSLSession[] = 293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "MIIFpQIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ" 294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH" 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "IWoJoQYCBFRDO46iBAICASyjggR6MIIEdjCCA16gAwIBAgIIK9dUvsPWSlUwDQYJ" 296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "KoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx" 297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTQxMDA4" 298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "MTIwNzU3WhcNMTUwMTA2MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK" 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v" 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB" 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "AQUAA4IBDwAwggEKAoIBAQCcKeLrplAC+Lofy8t/wDwtB6eu72CVp0cJ4V3lknN6" 302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "huH9ct6FFk70oRIh/VBNBBz900jYy+7111Jm1b8iqOTQ9aT5C7SEhNcQFJvqzH3e" 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "MPkb6ZSWGm1yGF7MCQTGQXF20Sk/O16FSjAynU/b3oJmOctcycWYkY0ytS/k3LBu" 304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "Id45PJaoMqjB0WypqvNeJHC3q5JjCB4RP7Nfx5jjHSrCMhw8lUMW4EaDxjaR9KDh" 305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "PLgjsk+LDIySRSRDaCQGhEOWLJZVLzLo4N6/UlctCHEllpBUSvEOyFga52qroGjg" 306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "rf3WOQ925MFwzd6AK+Ich0gDRg8sQfdLH5OuP1cfLfU1AgMBAAGjggFBMIIBPTAd" 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv" 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp" 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50" 310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBQ7a+CcxsZByOpc+xpYFcIbnUMZ" 311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "hTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv" 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw" 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCa" 314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "OXCBdoqUy5bxyq+Wrh1zsyyCFim1PH5VU2+yvDSWrgDY8ibRGJmfff3r4Lud5kal" 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "dKs9k8YlKD3ITG7P0YT/Rk8hLgfEuLcq5cc0xqmE42xJ+Eo2uzq9rYorc5emMCxf" 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "5L0TJOXZqHQpOEcuptZQ4OjdYMfSxk5UzueUhA3ogZKRcRkdB3WeWRp+nYRhx4St" 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "o2rt2A0MKmY9165GHUqMK9YaaXHDXqBu7Sefr1uSoAP9gyIJKeihMivsGqJ1TD6Z" 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "cc6LMe+dN2P8cZEQHtD1y296ul4Mivqk3jatUVL8/hCwgch9A8O4PGZq9WqBfEWm" 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "IyHh1dPtbg1lOXdYCWtjpAIEAKUDAgEUqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36S" 320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "YTcLEkXqKwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9B" 321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "sNHM362zZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yE" 322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "OTDKPNj3+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdA" 323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "i4gv7Y5oliyn"; 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 325e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// kCustomSession is a custom serialized SSL_SESSION generated by 326e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// filling in missing fields from |kOpenSSLSession|. This includes 327e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley// providing |peer_sha256|, so |peer| is not serialized. 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic const char kCustomSession[] = 329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ" 330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH" 331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE" 332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe" 333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751" 334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP" 335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG" 336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF"; 337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 33853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley// kBadSessionExtraField is a custom serialized SSL_SESSION generated by replacing 33953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley// the final (optional) element of |kCustomSession| with tag number 30. 34053b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langleystatic const char kBadSessionExtraField[] = 34153b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ" 34253b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH" 34353b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE" 34453b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe" 34553b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751" 34653b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP" 34753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG" 34853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBL4DBAEF"; 34953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley 35053b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley// kBadSessionVersion is a custom serialized SSL_SESSION generated by replacing 35153b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley// the version of |kCustomSession| with 2. 35253b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langleystatic const char kBadSessionVersion[] = 35353b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "MIIBdgIBAgICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ" 35453b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH" 35553b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE" 35653b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe" 35753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751" 35853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP" 35953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG" 36053b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF"; 36153b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley 362e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool DecodeBase64(std::vector<uint8_t> *out, const char *in) { 363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t len; 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EVP_DecodedLength(&len, strlen(in))) { 365d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "EVP_DecodedLength failed\n"); 366e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 369e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley out->resize(len); 370e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EVP_DecodeBase64(bssl::vector_data(out), &len, len, (const uint8_t *)in, 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley strlen(in))) { 372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "EVP_DecodeBase64 failed\n"); 373e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 375e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley out->resize(len); 376e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 379e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestSSL_SESSIONEncoding(const char *input_b64) { 380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *cptr; 381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *ptr; 382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 383e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Decode the input. 384e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley std::vector<uint8_t> input; 385e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!DecodeBase64(&input, input_b64)) { 386e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 389e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify the SSL_SESSION decodes. 390e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley cptr = bssl::vector_data(&input); 391e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedSSL_SESSION session(d2i_SSL_SESSION(NULL, &cptr, input.size())); 392e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!session || cptr != bssl::vector_data(&input) + input.size()) { 393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "d2i_SSL_SESSION failed\n"); 394e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 396d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 397e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify the SSL_SESSION encoding round-trips. 398e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley size_t encoded_len; 399e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedOpenSSLBytes encoded; 400e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley uint8_t *encoded_raw; 401e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!SSL_SESSION_to_bytes(session.get(), &encoded_raw, &encoded_len)) { 402d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "SSL_SESSION_to_bytes failed\n"); 403e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 404d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 405e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley encoded.reset(encoded_raw); 406e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (encoded_len != input.size() || 407e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley memcmp(bssl::vector_data(&input), encoded.get(), input.size()) != 0) { 408d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "SSL_SESSION_to_bytes did not round-trip\n"); 409e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 412e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // Verify the SSL_SESSION encoding round-trips via the legacy API. 413e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley int len = i2d_SSL_SESSION(session.get(), NULL); 414e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (len < 0 || (size_t)len != input.size()) { 415d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "i2d_SSL_SESSION(NULL) returned invalid length\n"); 416e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 417d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 418d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 419e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley encoded.reset((uint8_t *)OPENSSL_malloc(input.size())); 420e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!encoded) { 421d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "malloc failed\n"); 422e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 423d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 424e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 425e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ptr = encoded.get(); 426e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley len = i2d_SSL_SESSION(session.get(), &ptr); 427e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (len < 0 || (size_t)len != input.size()) { 428d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "i2d_SSL_SESSION returned invalid length\n"); 429e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 430d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 431e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (ptr != encoded.get() + input.size()) { 432d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "i2d_SSL_SESSION did not advance ptr correctly\n"); 433e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 434d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 435e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (memcmp(bssl::vector_data(&input), encoded.get(), input.size()) != 0) { 436d9e397b599b13d642138480a28c14db7a136bf0Adam Langley fprintf(stderr, "i2d_SSL_SESSION did not round-trip\n"); 437e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 438d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 439d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 440e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 441e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 442d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 44353b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langleystatic bool TestBadSSL_SESSIONEncoding(const char *input_b64) { 44453b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley std::vector<uint8_t> input; 44553b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley if (!DecodeBase64(&input, input_b64)) { 44653b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley return false; 44753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley } 44853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley 44953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley // Verify that the SSL_SESSION fails to decode. 45053b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley const uint8_t *ptr = bssl::vector_data(&input); 45153b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley ScopedSSL_SESSION session(d2i_SSL_SESSION(NULL, &ptr, input.size())); 45253b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley if (session) { 45353b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley fprintf(stderr, "d2i_SSL_SESSION unexpectedly succeeded\n"); 45453b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley return false; 45553b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley } 45653b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley ERR_clear_error(); 45753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley return true; 45853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley} 45953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley 460e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestDefaultVersion(uint16_t version, 461e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley const SSL_METHOD *(*method)(void)) { 462e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedSSL_CTX ctx(SSL_CTX_new(method())); 463e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!ctx) { 464e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 465d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 466e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return ctx->min_version == version && ctx->max_version == version; 467e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} 468d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 469e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool CipherGetRFCName(std::string *out, uint16_t value) { 470e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley const SSL_CIPHER *cipher = SSL_get_cipher_by_value(value); 471e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (cipher == NULL) { 472e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 473d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 474e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ScopedOpenSSLString rfc_name(SSL_CIPHER_get_rfc_name(cipher)); 47553b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley if (!rfc_name) { 47653b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley return false; 47753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley } 478e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley out->assign(rfc_name.get()); 479e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 480d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 481d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 482e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleytypedef struct { 483e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley int id; 484e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley const char *rfc_name; 485e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley} CIPHER_RFC_NAME_TEST; 486e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley 487e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const CIPHER_RFC_NAME_TEST kCipherRFCNameTests[] = { 488e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA" }, 489e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { SSL3_CK_RSA_RC4_128_MD5, "TLS_RSA_WITH_RC4_MD5" }, 490e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA" }, 491e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_DHE_RSA_WITH_AES_256_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" }, 492e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_DHE_RSA_WITH_AES_256_SHA256, 493e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" }, 494e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256, 495e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" }, 496e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384, 497e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" }, 498e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 499e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" }, 500e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 501e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" }, 502e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 503e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" }, 504e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_PSK_WITH_RC4_128_SHA, "TLS_PSK_WITH_RC4_SHA" }, 505dfb3ba68fd0011cba7d8e4c1a46295099fef85bfAdam Langley { TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA, 506dfb3ba68fd0011cba7d8e4c1a46295099fef85bfAdam Langley "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" }, 507e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley // These names are non-standard: 508e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 509e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" }, 510e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 511e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" }, 512e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}; 513d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 514e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic bool TestCipherGetRFCName(void) { 515e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley for (size_t i = 0; 516e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley i < sizeof(kCipherRFCNameTests) / sizeof(kCipherRFCNameTests[0]); i++) { 517e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley const CIPHER_RFC_NAME_TEST *test = &kCipherRFCNameTests[i]; 518e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley std::string rfc_name; 519e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!CipherGetRFCName(&rfc_name, test->id & 0xffff)) { 520e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(stderr, "SSL_CIPHER_get_rfc_name failed\n"); 521e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 522e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 523e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (rfc_name != test->rfc_name) { 524e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley fprintf(stderr, "SSL_CIPHER_get_rfc_name: got '%s', wanted '%s'\n", 525e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley rfc_name.c_str(), test->rfc_name); 526e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return false; 527e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 528d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 529e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley return true; 530d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 531d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 532d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint main(void) { 533d9e397b599b13d642138480a28c14db7a136bf0Adam Langley SSL_library_init(); 534d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 535e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!TestCipherRules() || 536e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestSSL_SESSIONEncoding(kOpenSSLSession) || 537e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestSSL_SESSIONEncoding(kCustomSession) || 53853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley !TestBadSSL_SESSIONEncoding(kBadSessionExtraField) || 53953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley !TestBadSSL_SESSIONEncoding(kBadSessionVersion) || 540e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestDefaultVersion(0, &TLS_method) || 541e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestDefaultVersion(SSL3_VERSION, &SSLv3_method) || 542e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestDefaultVersion(TLS1_VERSION, &TLSv1_method) || 543e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestDefaultVersion(TLS1_1_VERSION, &TLSv1_1_method) || 544e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestDefaultVersion(TLS1_2_VERSION, &TLSv1_2_method) || 545e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestDefaultVersion(0, &DTLS_method) || 546e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestDefaultVersion(DTLS1_VERSION, &DTLSv1_method) || 547e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestDefaultVersion(DTLS1_2_VERSION, &DTLSv1_2_method) || 548e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley !TestCipherGetRFCName()) { 549e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley ERR_print_errors_fp(stderr); 550d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 1; 551d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 552d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 553d9e397b599b13d642138480a28c14db7a136bf0Adam Langley printf("PASS\n"); 554d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 555d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 556