1 /* 2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include "inner.h" 26 27 static int 28 se_choose(const br_ssl_server_policy_class **pctx, 29 const br_ssl_server_context *cc, 30 br_ssl_server_choices *choices) 31 { 32 br_ssl_server_policy_ec_context *pc; 33 const br_suite_translated *st; 34 size_t u, st_num; 35 unsigned hash_id; 36 37 pc = (br_ssl_server_policy_ec_context *)pctx; 38 st = br_ssl_server_get_client_suites(cc, &st_num); 39 hash_id = br_ssl_choose_hash(br_ssl_server_get_client_hashes(cc) >> 8); 40 if (cc->eng.session.version < BR_TLS12) { 41 hash_id = br_sha1_ID; 42 } 43 choices->chain = pc->chain; 44 choices->chain_len = pc->chain_len; 45 for (u = 0; u < st_num; u ++) { 46 unsigned tt; 47 48 tt = st[u][1]; 49 switch (tt >> 12) { 50 case BR_SSLKEYX_ECDH_RSA: 51 if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0 52 && pc->cert_issuer_key_type == BR_KEYTYPE_RSA) 53 { 54 choices->cipher_suite = st[u][0]; 55 return 1; 56 } 57 break; 58 case BR_SSLKEYX_ECDH_ECDSA: 59 if ((pc->allowed_usages & BR_KEYTYPE_KEYX) != 0 60 && pc->cert_issuer_key_type == BR_KEYTYPE_EC) 61 { 62 choices->cipher_suite = st[u][0]; 63 return 1; 64 } 65 break; 66 case BR_SSLKEYX_ECDHE_ECDSA: 67 if ((pc->allowed_usages & BR_KEYTYPE_SIGN) != 0 68 && hash_id != 0) 69 { 70 choices->cipher_suite = st[u][0]; 71 choices->algo_id = hash_id + 0xFF00; 72 return 1; 73 } 74 break; 75 } 76 } 77 return 0; 78 } 79 80 static uint32_t 81 se_do_keyx(const br_ssl_server_policy_class **pctx, 82 unsigned char *data, size_t *len) 83 { 84 br_ssl_server_policy_ec_context *pc; 85 uint32_t r; 86 size_t xoff, xlen; 87 88 pc = (br_ssl_server_policy_ec_context *)pctx; 89 r = pc->iec->mul(data, *len, pc->sk->x, pc->sk->xlen, pc->sk->curve); 90 xoff = pc->iec->xoff(pc->sk->curve, &xlen); 91 memmove(data, data + xoff, xlen); 92 *len = xlen; 93 return r; 94 } 95 96 static size_t 97 se_do_sign(const br_ssl_server_policy_class **pctx, 98 unsigned algo_id, unsigned char *data, size_t hv_len, size_t len) 99 { 100 br_ssl_server_policy_ec_context *pc; 101 unsigned char hv[64]; 102 const br_hash_class *hc; 103 104 algo_id &= 0xFF; 105 pc = (br_ssl_server_policy_ec_context *)pctx; 106 hc = br_multihash_getimpl(pc->mhash, algo_id); 107 if (hc == NULL) { 108 return 0; 109 } 110 memcpy(hv, data, hv_len); 111 if (len < 139) { 112 return 0; 113 } 114 return pc->iecdsa(pc->iec, hc, hv, pc->sk, data); 115 } 116 117 static const br_ssl_server_policy_class se_policy_vtable = { 118 sizeof(br_ssl_server_policy_ec_context), 119 se_choose, 120 se_do_keyx, 121 se_do_sign 122 }; 123 124 /* see bearssl_ssl.h */ 125 void 126 br_ssl_server_set_single_ec(br_ssl_server_context *cc, 127 const br_x509_certificate *chain, size_t chain_len, 128 const br_ec_private_key *sk, unsigned allowed_usages, 129 unsigned cert_issuer_key_type, 130 const br_ec_impl *iec, br_ecdsa_sign iecdsa) 131 { 132 cc->chain_handler.single_ec.vtable = &se_policy_vtable; 133 cc->chain_handler.single_ec.chain = chain; 134 cc->chain_handler.single_ec.chain_len = chain_len; 135 cc->chain_handler.single_ec.sk = sk; 136 cc->chain_handler.single_ec.allowed_usages = allowed_usages; 137 cc->chain_handler.single_ec.cert_issuer_key_type = cert_issuer_key_type; 138 cc->chain_handler.single_ec.mhash = &cc->eng.mhash; 139 cc->chain_handler.single_ec.iec = iec; 140 cc->chain_handler.single_ec.iecdsa = iecdsa; 141 cc->policy_vtable = &cc->chain_handler.single_ec.vtable; 142 } 143